From eb421b562aabe73ebd9d92e2684f995dd365776a Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 23 Aug 2020 18:17:03 -0400 Subject: [PATCH 001/139] Heap code cleanup Ideally some of the macros will be turned into functions, but maybe not. --- kernel/lib/linked_list.cpp | 16 +- kernel/mem/heap.cpp | 238 +++++++----------- .../usr/include/kernel/lib/linked_list.hpp | 53 ++++ sysroot/usr/include/kernel/mem/heap.hpp | 15 ++ 4 files changed, 169 insertions(+), 153 deletions(-) diff --git a/kernel/lib/linked_list.cpp b/kernel/lib/linked_list.cpp index 5b315bd5..2d7214e9 100644 --- a/kernel/lib/linked_list.cpp +++ b/kernel/lib/linked_list.cpp @@ -12,18 +12,18 @@ */ #include -#include +#include // initialize a one element DList void dlist_init(DList *dlist) { - //printf("%s(%p)\n", __FUNCTION__, dlist); + //px_kprintf("%s(%p)\n", __FUNCTION__, dlist); dlist->next = dlist; dlist->prev = dlist; } // insert d2 after d1 void dlist_insert_after(DList *d1, DList *d2) { - //printf("%s(%p, %p)\n", __FUNCTION__, d1, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1, d2); DList *n1 = d1->next; DList *e2 = d2->prev; @@ -35,7 +35,7 @@ void dlist_insert_after(DList *d1, DList *d2) { // insert d2 before d1 void dlist_insert_before(DList *d1, DList *d2) { - //printf("%s(%p, %p)\n", __FUNCTION__, d1, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1, d2); DList *e1 = d1->prev; DList *e2 = d2->prev; @@ -47,7 +47,7 @@ void dlist_insert_before(DList *d1, DList *d2) { // remove d from the list void dlist_remove(DList *d) { - //printf("%s(%p)\n", __FUNCTION__, d); + //px_kprintf("%s(%p)\n", __FUNCTION__, d); d->prev->next = d->next; d->next->prev = d->prev; d->next = d; @@ -56,7 +56,7 @@ void dlist_remove(DList *d) { // push d2 to the front of the d1p list void dlist_push(DList **d1p, DList *d2) { - //printf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); if (*d1p != NULL) { dlist_insert_before(*d1p, d2); } @@ -65,7 +65,7 @@ void dlist_push(DList **d1p, DList *d2) { // pop the front of the dp list DList* dlist_pop(DList **dp) { - //printf("%s(%p)\n", __FUNCTION__, dp); + //px_kprintf("%s(%p)\n", __FUNCTION__, dp); DList *d1 = *dp; DList *d2 = d1->next; dlist_remove(d1); @@ -79,7 +79,7 @@ DList* dlist_pop(DList **dp) { // remove d2 from the list, advancing d1p if needed void dlist_remove_from(DList **d1p, DList *d2) { - //printf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); if (*d1p == d2) { dlist_pop(d1p); } else { diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index f6706045..aa1e0dea 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -14,174 +14,110 @@ * */ -#include -#include #include +#include #include -#include - -#define typeof __typeof__ +#include +#include +#include -#define MEM_SIZE (1024*1024*2) // 256 -#define MAX_BLOCK (1024*1024) #define NUM_SLOTS 1024 - -#define DLIST_REMOVE_FROM(h, d, l) \ - { \ - typeof(**h) **h_ = h, *d_ = d; \ - DList *head = &(*h_)->l; \ - dlist_remove_from(&head, &d_->l); \ - if (head == NULL) { \ - *h_ = NULL; \ - } else { \ - *h_ = CONTAINER(typeof(**h), l, head); \ - } \ - } - -#define DLIST_PUSH(h, v, l) \ - { \ - typeof(*v) **h_ = h, *v_ = v; \ - DList *head = &(*h_)->l; \ - if (*h_ == NULL) head = NULL; \ - dlist_push(&head, &v_->l); \ - *h_ = CONTAINER(typeof(*v), l, head); \ - } - -#define DLIST_POP(h, l) \ - ({ \ - typeof(**h) **h_ = h; \ - DList *head = &(*h_)->l; \ - DList *res = dlist_pop(&head); \ - if (head == NULL) { \ - *h_ = NULL; \ - } else { \ - *h_ = CONTAINER(typeof(**h), l, head); \ - } \ - CONTAINER(typeof(**h), l, res); \ - }) - -#define DLIST_ITERATOR_BEGIN(h, l, it) \ - { \ - typeof(*h) *h_ = h; \ - DList *last_##it = h_->l.prev, *iter_##it = &h_->l, *next_##it; \ - do { \ - if (iter_##it == last_##it) { \ - next_##it = NULL; \ - } else { \ - next_##it = iter_##it->next; \ - } \ - typeof(*h)* it = CONTAINER(typeof(*h), l, iter_##it); - -#define DLIST_ITERATOR_END(it) \ - } while((iter_##it = next_##it)); \ - } - -#define DLIST_ITERATOR_REMOVE_FROM(h, it, l) DLIST_REMOVE_FROM(h, iter_##it, l) - #define CONTAINER(C, l, v) ((C*)(((char*)v) - (intptr_t)&(((C*)0)->l))) -#define OFFSETOF(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) -#define DLIST_INIT(v, l) dlist_init(&v->l) - -typedef struct Chunk Chunk; -struct Chunk { - DList all; - int used; - union { - char data[0]; - DList free; - }; -}; - -enum { - NUM_SIZES = 32, - ALIGN = 4, - MIN_SIZE = sizeof(DList), - HEADER_SIZE = OFFSETOF(Chunk, data), -}; - -Chunk* free_chunk[NUM_SIZES] = { NULL }; + size_t mem_free = 0; size_t mem_used = 0; size_t mem_meta = 0; -Chunk* first = NULL; -Chunk* last = NULL; -char MEM[MEM_SIZE] = { 0 }; +px_heap_chunk_t* free_chunk[NUM_SIZES] = { NULL }; +px_heap_chunk_t* first = NULL; +px_heap_chunk_t* last = NULL; + void* slot[NUM_SLOTS] = { NULL }; -static void memory_chunk_init(Chunk *chunk) { - //printf("%s(%p)\n", __FUNCTION__, chunk); - DLIST_INIT(chunk, all); +static void px_memory_chunk_init(px_heap_chunk_t *chunk) { + px_kprintf("%s(%p)\n", __FUNCTION__, chunk); + dlist_init(&chunk->all); chunk->used = 0; - DLIST_INIT(chunk, free); + dlist_init(&chunk->free); } -static size_t memory_chunk_size(const Chunk *chunk) { - //printf("%s(%p)\n", __FUNCTION__, chunk); +static size_t px_memory_chunk_size(const px_heap_chunk_t *chunk) { + px_kprintf("%s(%p)\n", __FUNCTION__, chunk); char *end = (char*)(chunk->all.next); char *start = (char*)(&chunk->all); return (end - start) - HEADER_SIZE; } -static int memory_chunk_slot(size_t size) { +static int px_memory_chunk_slot(size_t size) { int n = -1; while(size > 0) { - ++n; - size /= 2; + ++n; + size /= 2; } return n; } -void mrvn_memory_init(void *mem, size_t size) { +void px_memory_init(void *mem, size_t size) { char *mem_start = (char *)(((uintptr_t)mem + ALIGN - 1) & (~(ALIGN - 1))); char *mem_end = (char *)(((uintptr_t)mem + size) & (~(ALIGN - 1))); - first = (Chunk*)mem_start; - Chunk *second = first + 1; - last = ((Chunk*)mem_end) - 1; - memory_chunk_init(first); - memory_chunk_init(second); - memory_chunk_init(last); + first = (px_heap_chunk_t*)mem_start; + px_heap_chunk_t *second = first + 1; + last = ((px_heap_chunk_t*)mem_end) - 1; + px_memory_chunk_init(first); + px_memory_chunk_init(second); + px_memory_chunk_init(last); dlist_insert_after(&first->all, &second->all); dlist_insert_after(&second->all, &last->all); // make first/last as used so they never get merged first->used = 1; last->used = 1; - size_t len = memory_chunk_size(second); - int n = memory_chunk_slot(len); - //printf("%s(%p, %#lx) : adding chunk %#lx [%d]\n", __FUNCTION__, mem, size, len, n); + size_t len = px_memory_chunk_size(second); + int n = px_memory_chunk_slot(len); + + px_kprintf("%s(%p, %#lx) : adding chunk %#lx [%d]\n", __FUNCTION__, mem, size, len, n); + DLIST_PUSH(&free_chunk[n], second, free); mem_free = len - HEADER_SIZE; - mem_meta = sizeof(Chunk) * 2 + HEADER_SIZE; + mem_meta = sizeof(px_heap_chunk_t) * 2 + HEADER_SIZE; } -void *mrvn_malloc(size_t size) { - //printf("%s(%#lx)\n", __FUNCTION__, size); +void *malloc(size_t size) { + px_kprintf("%s(%#lx)\n", __FUNCTION__, size); + size = (size + ALIGN - 1) & (~(ALIGN - 1)); - if (size < MIN_SIZE) size = MIN_SIZE; + if (size < MIN_SIZE) { + size = MIN_SIZE; + } - int n = memory_chunk_slot(size - 1) + 1; + int n = px_memory_chunk_slot(size - 1) + 1; - if (n >= NUM_SIZES) return NULL; + if (n >= NUM_SIZES) { + return NULL; + } while(!free_chunk[n]) { ++n; if (n >= NUM_SIZES) return NULL; } - Chunk *chunk = DLIST_POP(&free_chunk[n], free); - size_t size2 = memory_chunk_size(chunk); - //printf("@ %p [%#lx]\n", chunk, size2); + px_heap_chunk_t *chunk = DLIST_POP(&free_chunk[n], free); + size_t size2 = px_memory_chunk_size(chunk); + + px_kprintf("@ %p [%#lx]\n", chunk, size2); + size_t len = 0; - if (size + sizeof(Chunk) <= size2) { - Chunk *chunk2 = (Chunk*)(((char*)chunk) + HEADER_SIZE + size); - memory_chunk_init(chunk2); + if (size + sizeof(px_heap_chunk_t) <= size2) { + px_heap_chunk_t *chunk2 = (px_heap_chunk_t*)(((char*)chunk) + HEADER_SIZE + size); + px_memory_chunk_init(chunk2); dlist_insert_after(&chunk->all, &chunk2->all); - len = memory_chunk_size(chunk2); - int n = memory_chunk_slot(len); - //printf(" adding chunk @ %p %#lx [%d]\n", chunk2, len, n); + len = px_memory_chunk_size(chunk2); + int n = px_memory_chunk_slot(len); + + px_kprintf(" adding chunk @ %p %#lx [%d]\n", chunk2, len, n); + DLIST_PUSH(&free_chunk[n], chunk2, free); mem_meta += HEADER_SIZE; mem_free += len - HEADER_SIZE; @@ -189,75 +125,87 @@ void *mrvn_malloc(size_t size) { chunk->used = 1; //memset(chunk->data, 0xAA, size); - //printf("AAAA\n"); + px_kprintf("AAAA\n"); + mem_free -= size2; mem_used += size2 - len - HEADER_SIZE; - //printf(" = %p [%p]\n", chunk->data, chunk); + px_kprintf(" = %p [%p]\n", chunk->data, chunk); return chunk->data; } -static void remove_free(Chunk *chunk) { - size_t len = memory_chunk_size(chunk); - int n = memory_chunk_slot(len); - //printf("%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); +static void px_remove_free(px_heap_chunk_t *chunk) { + size_t len = px_memory_chunk_size(chunk); + int n = px_memory_chunk_slot(len); + + px_kprintf("%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); mem_free -= len - HEADER_SIZE; } -static void push_free(Chunk *chunk) { - size_t len = memory_chunk_size(chunk); - int n = memory_chunk_slot(len); - //printf("%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); +static void px_push_free(px_heap_chunk_t *chunk) { + size_t len = px_memory_chunk_size(chunk); + int n = px_memory_chunk_slot(len); + + px_kprintf("%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + DLIST_PUSH(&free_chunk[n], chunk, free); mem_free += len - HEADER_SIZE; } -void mrvn_free(void *mem) { - Chunk *chunk = (Chunk*)((char*)mem - HEADER_SIZE); - Chunk *next = CONTAINER(Chunk, all, chunk->all.next); - Chunk *prev = CONTAINER(Chunk, all, chunk->all.prev); +void free(void *mem) { + px_heap_chunk_t *chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); + px_heap_chunk_t *next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); + px_heap_chunk_t *prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); + + px_kprintf("%s(%p): @%p %#lx [%d]\n", + __FUNCTION__, + mem, + chunk, + px_memory_chunk_size(chunk), + px_memory_chunk_slot(px_memory_chunk_size(chunk)) + ); - //printf("%s(%p): @%p %#lx [%d]\n", __FUNCTION__, mem, chunk, memory_chunk_size(chunk), memory_chunk_slot(memory_chunk_size(chunk))); - mem_used -= memory_chunk_size(chunk); + mem_used -= px_memory_chunk_size(chunk); if (next->used == 0) { // merge in next - remove_free(next); + px_remove_free(next); dlist_remove(&next->all); - //memset(next, 0xDD, sizeof(Chunk)); + //memset(next, 0xDD, sizeof(px_heap_chunk_t)); mem_meta -= HEADER_SIZE; mem_free += HEADER_SIZE; } if (prev->used == 0) { // merge to prev - remove_free(prev); + px_remove_free(prev); dlist_remove(&chunk->all); - //memset(chunk, 0xDD, sizeof(Chunk)); - push_free(prev); + //memset(chunk, 0xDD, sizeof(px_heap_chunk_t)); + px_push_free(prev); mem_meta -= HEADER_SIZE; mem_free += HEADER_SIZE; } else { // make chunk as free chunk->used = 0; - DLIST_INIT(chunk, free); - push_free(chunk); + dlist_init(&chunk->free); + px_push_free(chunk); } } void check(void) { int i; - Chunk *t = last; + px_heap_chunk_t *t = last; DLIST_ITERATOR_BEGIN(first, all, it) { - assert(CONTAINER(Chunk, all, it->all.prev) == t); + assert(CONTAINER(px_heap_chunk_t, all, it->all.prev) == t); t = it; } DLIST_ITERATOR_END(it); for(i = 0; i < NUM_SIZES; ++i) { if (free_chunk[i]) { - t = CONTAINER(Chunk, free, free_chunk[i]->free.prev); + t = CONTAINER(px_heap_chunk_t, free, free_chunk[i]->free.prev); DLIST_ITERATOR_BEGIN(free_chunk[i], free, it) { - assert(CONTAINER(Chunk, free, it->free.prev) == t); + assert(CONTAINER(px_heap_chunk_t, free, it->free.prev) == t); t = it; } DLIST_ITERATOR_END(it); } diff --git a/sysroot/usr/include/kernel/lib/linked_list.hpp b/sysroot/usr/include/kernel/lib/linked_list.hpp index b35346b2..01a24c50 100644 --- a/sysroot/usr/include/kernel/lib/linked_list.hpp +++ b/sysroot/usr/include/kernel/lib/linked_list.hpp @@ -14,6 +14,59 @@ #define PANIX_LIB_LINKED_LIST #include +#include + +#define DLIST_REMOVE_FROM(h, d, l) \ + { \ + __typeof__(**h) **h_ = h, *d_ = d; \ + DList *head = &(*h_)->l; \ + dlist_remove_from(&head, &d_->l); \ + if (head == NULL) { \ + *h_ = NULL; \ + } else { \ + *h_ = CONTAINER(__typeof__(**h), l, head); \ + } \ + } + +#define DLIST_PUSH(h, v, l) \ + { \ + __typeof__(*v) **h_ = h, *v_ = v; \ + DList *head = &(*h_)->l; \ + if (*h_ == NULL) head = NULL; \ + dlist_push(&head, &v_->l); \ + *h_ = CONTAINER(__typeof__(*v), l, head); \ + } + +#define DLIST_POP(h, l) \ + ({ \ + __typeof__(**h) **h_ = h; \ + DList *head = &(*h_)->l; \ + DList *res = dlist_pop(&head); \ + if (head == NULL) { \ + *h_ = NULL; \ + } else { \ + *h_ = CONTAINER(__typeof__(**h), l, head); \ + } \ + CONTAINER(__typeof__(**h), l, res); \ + }) + +#define DLIST_ITERATOR_BEGIN(h, l, it) \ + { \ + __typeof__(*h) *h_ = h; \ + DList *last_##it = h_->l.prev, *iter_##it = &h_->l, *next_##it; \ + do { \ + if (iter_##it == last_##it) { \ + next_##it = NULL; \ + } else { \ + next_##it = iter_##it->next; \ + } \ + __typeof__(*h)* it = CONTAINER(__typeof__(*h), l, iter_##it); + +#define DLIST_ITERATOR_END(it) \ + } while((iter_##it = next_##it)); \ + } + +#define DLIST_ITERATOR_REMOVE_FROM(h, it, l) DLIST_REMOVE_FROM(h, iter_##it, l) typedef struct DList { DList *next; diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 6d0e5e9b..42b51b91 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -19,5 +19,20 @@ #include #include +typedef struct px_heap_chunk { + DList all; + int used; + union { + char data[0]; + DList free; + }; +} px_heap_chunk_t; + +enum { + NUM_SIZES = 32, + ALIGN = 4, + MIN_SIZE = sizeof(DList), + HEADER_SIZE = __builtin_offsetof(px_heap_chunk_t, data) +}; #endif /* PANIX_MEM_HEAP */ \ No newline at end of file From 42c0b0d50db9c86cf3bf18fefd35777f90d68f7a Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 23 Aug 2020 18:35:38 -0400 Subject: [PATCH 002/139] Heap code is possibly working --- kernel/main.cpp | 5 +- kernel/mem/heap.cpp | 129 +++++++++++++----------- sysroot/usr/include/kernel/mem/heap.hpp | 20 ++++ 3 files changed, 91 insertions(+), 63 deletions(-) diff --git a/kernel/main.cpp b/kernel/main.cpp index ae58ee39..bb6e227b 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -91,12 +91,11 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma px_gdt_install(); // Initialize the Global Descriptor Table px_isr_install(); // Initialize Interrupt Service Requests px_rs232_init(RS_232_COM1); // RS232 Serial - px_paging_init(0); // Initialize paging service + px_paging_init(0); // Initialize paging service (0 is placeholder) + px_heap_init(32*PAGE_SIZE); // Initialize the kernel heap px_kbd_init(); // Initialize PS/2 Keyboard px_rtc_init(); // Initialize Real Time Clock px_timer_init(1000); // Programmable Interrupt Timer (1ms) - // Now that we've initialized our core kernel necessities - // we can initialize paging. // Enable interrupts now that we're out of a critical area px_interrupts_enable(); // Print some info to show we did things right diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index aa1e0dea..1100847a 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -11,12 +11,13 @@ * can be found at the link below. * * https://wiki.osdev.org/User:Mrvn/LinkedListBucketHeapImplementation - * + * */ #include #include #include +#include #include #include #include @@ -34,17 +35,17 @@ px_heap_chunk_t* last = NULL; void* slot[NUM_SLOTS] = { NULL }; -static void px_memory_chunk_init(px_heap_chunk_t *chunk) { +static void px_memory_chunk_init(px_heap_chunk_t* chunk) { px_kprintf("%s(%p)\n", __FUNCTION__, chunk); dlist_init(&chunk->all); chunk->used = 0; dlist_init(&chunk->free); } -static size_t px_memory_chunk_size(const px_heap_chunk_t *chunk) { +static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { px_kprintf("%s(%p)\n", __FUNCTION__, chunk); - char *end = (char*)(chunk->all.next); - char *start = (char*)(&chunk->all); + char* end = (char*)(chunk->all.next); + char* start = (char*)(&chunk->all); return (end - start) - HEADER_SIZE; } @@ -57,32 +58,80 @@ static int px_memory_chunk_slot(size_t size) { return n; } -void px_memory_init(void *mem, size_t size) { - char *mem_start = (char *)(((uintptr_t)mem + ALIGN - 1) & (~(ALIGN - 1))); - char *mem_end = (char *)(((uintptr_t)mem + size) & (~(ALIGN - 1))); +static void px_remove_free(px_heap_chunk_t* chunk) { + size_t len = px_memory_chunk_size(chunk); + int n = px_memory_chunk_slot(len); + + px_kprintf("%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + + DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); + mem_free -= len - HEADER_SIZE; +} + +static void px_push_free(px_heap_chunk_t* chunk) { + size_t len = px_memory_chunk_size(chunk); + int n = px_memory_chunk_slot(len); + + px_kprintf("%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + + DLIST_PUSH(&free_chunk[n], chunk, free); + mem_free += len - HEADER_SIZE; +} + +void check(void) { + int i; + px_heap_chunk_t* t = last; + + DLIST_ITERATOR_BEGIN(first, all, it) { + assert(CONTAINER(px_heap_chunk_t, all, it->all.prev) == t); + t = it; + } DLIST_ITERATOR_END(it); + + for(i = 0; i < NUM_SIZES; ++i) { + if (free_chunk[i]) { + t = CONTAINER(px_heap_chunk_t, free, free_chunk[i]->free.prev); + DLIST_ITERATOR_BEGIN(free_chunk[i], free, it) { + assert(CONTAINER(px_heap_chunk_t, free, it->free.prev) == t); + t = it; + } DLIST_ITERATOR_END(it); + } + } +} + +void px_heap_init(size_t size) { + // Request a new page with the given size. Get the page address. + void* mem = px_get_new_page(size); + + // Use the page we got as the memory for the heap + char* mem_start = (char*)(((uintptr_t)mem + ALIGN - 1) & (~(ALIGN - 1))); + char* mem_end = (char*)(((uintptr_t)mem + size) & (~(ALIGN - 1))); first = (px_heap_chunk_t*)mem_start; - px_heap_chunk_t *second = first + 1; + px_heap_chunk_t* second = first + 1; last = ((px_heap_chunk_t*)mem_end) - 1; + + // Initialize the heap chunks px_memory_chunk_init(first); px_memory_chunk_init(second); px_memory_chunk_init(last); dlist_insert_after(&first->all, &second->all); dlist_insert_after(&second->all, &last->all); + // make first/last as used so they never get merged first->used = 1; last->used = 1; - + // Get the sizes and number of chunks size_t len = px_memory_chunk_size(second); int n = px_memory_chunk_slot(len); px_kprintf("%s(%p, %#lx) : adding chunk %#lx [%d]\n", __FUNCTION__, mem, size, len, n); + // Push them onto the linked list and update tracking variables DLIST_PUSH(&free_chunk[n], second, free); mem_free = len - HEADER_SIZE; mem_meta = sizeof(px_heap_chunk_t) * 2 + HEADER_SIZE; } -void *malloc(size_t size) { +void* malloc(size_t size) { px_kprintf("%s(%#lx)\n", __FUNCTION__, size); size = (size + ALIGN - 1) & (~(ALIGN - 1)); @@ -102,7 +151,7 @@ void *malloc(size_t size) { if (n >= NUM_SIZES) return NULL; } - px_heap_chunk_t *chunk = DLIST_POP(&free_chunk[n], free); + px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); size_t size2 = px_memory_chunk_size(chunk); px_kprintf("@ %p [%#lx]\n", chunk, size2); @@ -110,7 +159,7 @@ void *malloc(size_t size) { size_t len = 0; if (size + sizeof(px_heap_chunk_t) <= size2) { - px_heap_chunk_t *chunk2 = (px_heap_chunk_t*)(((char*)chunk) + HEADER_SIZE + size); + px_heap_chunk_t* chunk2 = (px_heap_chunk_t*)(((char*)chunk) + HEADER_SIZE + size); px_memory_chunk_init(chunk2); dlist_insert_after(&chunk->all, &chunk2->all); len = px_memory_chunk_size(chunk2); @@ -124,7 +173,7 @@ void *malloc(size_t size) { } chunk->used = 1; - //memset(chunk->data, 0xAA, size); + memset(chunk->data, 0xAA, size); px_kprintf("AAAA\n"); mem_free -= size2; @@ -133,30 +182,10 @@ void *malloc(size_t size) { return chunk->data; } -static void px_remove_free(px_heap_chunk_t *chunk) { - size_t len = px_memory_chunk_size(chunk); - int n = px_memory_chunk_slot(len); - - px_kprintf("%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); - - DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); - mem_free -= len - HEADER_SIZE; -} - -static void px_push_free(px_heap_chunk_t *chunk) { - size_t len = px_memory_chunk_size(chunk); - int n = px_memory_chunk_slot(len); - - px_kprintf("%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); - - DLIST_PUSH(&free_chunk[n], chunk, free); - mem_free += len - HEADER_SIZE; -} - -void free(void *mem) { - px_heap_chunk_t *chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); - px_heap_chunk_t *next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); - px_heap_chunk_t *prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); +void free(void* mem) { + px_heap_chunk_t* chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); + px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); + px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); px_kprintf("%s(%p): @%p %#lx [%d]\n", __FUNCTION__, @@ -172,7 +201,7 @@ void free(void *mem) { // merge in next px_remove_free(next); dlist_remove(&next->all); - //memset(next, 0xDD, sizeof(px_heap_chunk_t)); + memset(next, 0xDD, sizeof(px_heap_chunk_t)); mem_meta -= HEADER_SIZE; mem_free += HEADER_SIZE; } @@ -180,7 +209,7 @@ void free(void *mem) { // merge to prev px_remove_free(prev); dlist_remove(&chunk->all); - //memset(chunk, 0xDD, sizeof(px_heap_chunk_t)); + memset(chunk, 0xDD, sizeof(px_heap_chunk_t)); px_push_free(prev); mem_meta -= HEADER_SIZE; mem_free += HEADER_SIZE; @@ -191,23 +220,3 @@ void free(void *mem) { px_push_free(chunk); } } - -void check(void) { - int i; - px_heap_chunk_t *t = last; - - DLIST_ITERATOR_BEGIN(first, all, it) { - assert(CONTAINER(px_heap_chunk_t, all, it->all.prev) == t); - t = it; - } DLIST_ITERATOR_END(it); - - for(i = 0; i < NUM_SIZES; ++i) { - if (free_chunk[i]) { - t = CONTAINER(px_heap_chunk_t, free, free_chunk[i]->free.prev); - DLIST_ITERATOR_BEGIN(free_chunk[i], free, it) { - assert(CONTAINER(px_heap_chunk_t, free, it->free.prev) == t); - t = it; - } DLIST_ITERATOR_END(it); - } - } -} diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 42b51b91..85554829 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -35,4 +35,24 @@ enum { HEADER_SIZE = __builtin_offsetof(px_heap_chunk_t, data) }; +/** + * @brief Initializes the kernel heap. + * + * @param size Number of bytes to be used for the heap. + */ +void px_heap_init(size_t size); +/** + * @brief Dynamically allocate memory. + * + * @param size Number of bytes to be allocated. + * @return void* Address of allocated memory. + */ +void* malloc(size_t size); +/** + * @brief Frees dynamically allocated memory + * + * @param mem Address of memory to be freed. + */ +void free(void* mem); + #endif /* PANIX_MEM_HEAP */ \ No newline at end of file From a194f4e4987973d51d3370d2d9fd3716f1af201b Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 23 Aug 2020 18:54:35 -0400 Subject: [PATCH 003/139] Moved heap output to serial --- kernel/mem/heap.cpp | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index 1100847a..947e1bb1 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #define NUM_SLOTS 1024 @@ -34,16 +35,19 @@ px_heap_chunk_t* first = NULL; px_heap_chunk_t* last = NULL; void* slot[NUM_SLOTS] = { NULL }; +char dbg_buf[64] = {0}; static void px_memory_chunk_init(px_heap_chunk_t* chunk) { - px_kprintf("%s(%p)\n", __FUNCTION__, chunk); + px_ksprintf(dbg_buf, "%s(%p)\n", __FUNCTION__, chunk); + px_rs232_print(dbg_buf); dlist_init(&chunk->all); chunk->used = 0; dlist_init(&chunk->free); } static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { - px_kprintf("%s(%p)\n", __FUNCTION__, chunk); + px_ksprintf(dbg_buf, "%s(%p)\n", __FUNCTION__, chunk); + px_rs232_print(dbg_buf); char* end = (char*)(chunk->all.next); char* start = (char*)(&chunk->all); return (end - start) - HEADER_SIZE; @@ -62,7 +66,8 @@ static void px_remove_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); - px_kprintf("%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + px_ksprintf(dbg_buf, "%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + px_rs232_print(dbg_buf); DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); mem_free -= len - HEADER_SIZE; @@ -72,7 +77,8 @@ static void px_push_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); - px_kprintf("%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + px_ksprintf(dbg_buf, "%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + px_rs232_print(dbg_buf); DLIST_PUSH(&free_chunk[n], chunk, free); mem_free += len - HEADER_SIZE; @@ -123,7 +129,8 @@ void px_heap_init(size_t size) { size_t len = px_memory_chunk_size(second); int n = px_memory_chunk_slot(len); - px_kprintf("%s(%p, %#lx) : adding chunk %#lx [%d]\n", __FUNCTION__, mem, size, len, n); + px_ksprintf(dbg_buf, "%s(%p, %#lx) : adding chunk %#lx [%d]\n", __FUNCTION__, mem, size, len, n); + px_rs232_print(dbg_buf); // Push them onto the linked list and update tracking variables DLIST_PUSH(&free_chunk[n], second, free); @@ -132,7 +139,8 @@ void px_heap_init(size_t size) { } void* malloc(size_t size) { - px_kprintf("%s(%#lx)\n", __FUNCTION__, size); + px_ksprintf(dbg_buf, "%s(%#lx)\n", __FUNCTION__, size); + px_rs232_print(dbg_buf); size = (size + ALIGN - 1) & (~(ALIGN - 1)); @@ -154,7 +162,8 @@ void* malloc(size_t size) { px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); size_t size2 = px_memory_chunk_size(chunk); - px_kprintf("@ %p [%#lx]\n", chunk, size2); + px_ksprintf(dbg_buf, "@ %p [%#lx]\n", chunk, size2); + px_rs232_print(dbg_buf); size_t len = 0; @@ -165,7 +174,8 @@ void* malloc(size_t size) { len = px_memory_chunk_size(chunk2); int n = px_memory_chunk_slot(len); - px_kprintf(" adding chunk @ %p %#lx [%d]\n", chunk2, len, n); + px_ksprintf(dbg_buf, " adding chunk @ %p %#lx [%d]\n", chunk2, len, n); + px_rs232_print(dbg_buf); DLIST_PUSH(&free_chunk[n], chunk2, free); mem_meta += HEADER_SIZE; @@ -174,11 +184,13 @@ void* malloc(size_t size) { chunk->used = 1; memset(chunk->data, 0xAA, size); - px_kprintf("AAAA\n"); + px_ksprintf(dbg_buf, "AAAA\n"); + px_rs232_print(dbg_buf); mem_free -= size2; mem_used += size2 - len - HEADER_SIZE; - px_kprintf(" = %p [%p]\n", chunk->data, chunk); + px_ksprintf(dbg_buf, " = %p [%p]\n", chunk->data, chunk); + px_rs232_print(dbg_buf); return chunk->data; } @@ -187,13 +199,14 @@ void free(void* mem) { px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); - px_kprintf("%s(%p): @%p %#lx [%d]\n", + px_ksprintf(dbg_buf, "%s(%p): @%p %#lx [%d]\n", __FUNCTION__, mem, chunk, px_memory_chunk_size(chunk), px_memory_chunk_slot(px_memory_chunk_size(chunk)) ); + px_rs232_print(dbg_buf); mem_used -= px_memory_chunk_size(chunk); From 6cd51ea8c229083e262d26b6d332b2c767eab269 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 23 Aug 2020 19:00:50 -0400 Subject: [PATCH 004/139] Fixed printf formatting --- kernel/mem/heap.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index 947e1bb1..3ff5883b 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -38,7 +38,7 @@ void* slot[NUM_SLOTS] = { NULL }; char dbg_buf[64] = {0}; static void px_memory_chunk_init(px_heap_chunk_t* chunk) { - px_ksprintf(dbg_buf, "%s(%p)\n", __FUNCTION__, chunk); + px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); px_rs232_print(dbg_buf); dlist_init(&chunk->all); chunk->used = 0; @@ -46,7 +46,7 @@ static void px_memory_chunk_init(px_heap_chunk_t* chunk) { } static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { - px_ksprintf(dbg_buf, "%s(%p)\n", __FUNCTION__, chunk); + px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); px_rs232_print(dbg_buf); char* end = (char*)(chunk->all.next); char* start = (char*)(&chunk->all); @@ -66,7 +66,7 @@ static void px_remove_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); - px_ksprintf(dbg_buf, "%s(%p) : removing chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + px_ksprintf(dbg_buf, "%s(0x%p) : removing chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); px_rs232_print(dbg_buf); DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); @@ -77,7 +77,7 @@ static void px_push_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); - px_ksprintf(dbg_buf, "%s(%p) : adding chunk %#lx [%d]\n", __FUNCTION__, chunk, len, n); + px_ksprintf(dbg_buf, "%s(0x%p) : adding chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); px_rs232_print(dbg_buf); DLIST_PUSH(&free_chunk[n], chunk, free); @@ -129,7 +129,7 @@ void px_heap_init(size_t size) { size_t len = px_memory_chunk_size(second); int n = px_memory_chunk_slot(len); - px_ksprintf(dbg_buf, "%s(%p, %#lx) : adding chunk %#lx [%d]\n", __FUNCTION__, mem, size, len, n); + px_ksprintf(dbg_buf, "%s(0x%p, 0x%lx) : adding chunk 0x%lx [%d]\n", __FUNCTION__, mem, size, len, n); px_rs232_print(dbg_buf); // Push them onto the linked list and update tracking variables @@ -139,7 +139,7 @@ void px_heap_init(size_t size) { } void* malloc(size_t size) { - px_ksprintf(dbg_buf, "%s(%#lx)\n", __FUNCTION__, size); + px_ksprintf(dbg_buf, "%s(0x%lx)\n", __FUNCTION__, size); px_rs232_print(dbg_buf); size = (size + ALIGN - 1) & (~(ALIGN - 1)); @@ -162,7 +162,7 @@ void* malloc(size_t size) { px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); size_t size2 = px_memory_chunk_size(chunk); - px_ksprintf(dbg_buf, "@ %p [%#lx]\n", chunk, size2); + px_ksprintf(dbg_buf, "@ 0x%p [0x%lx]\n", chunk, size2); px_rs232_print(dbg_buf); size_t len = 0; @@ -174,7 +174,7 @@ void* malloc(size_t size) { len = px_memory_chunk_size(chunk2); int n = px_memory_chunk_slot(len); - px_ksprintf(dbg_buf, " adding chunk @ %p %#lx [%d]\n", chunk2, len, n); + px_ksprintf(dbg_buf, " adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); px_rs232_print(dbg_buf); DLIST_PUSH(&free_chunk[n], chunk2, free); @@ -199,7 +199,7 @@ void free(void* mem) { px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); - px_ksprintf(dbg_buf, "%s(%p): @%p %#lx [%d]\n", + px_ksprintf(dbg_buf, "%s(0x%p): 0x@%p 0x%lx [%d]\n", __FUNCTION__, mem, chunk, From 8baee9d88e2c097b64fd21a07523433e0a0b06d8 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 23 Aug 2020 19:04:49 -0400 Subject: [PATCH 005/139] Fixes Document Magic 0x80000000 (Issue #96) --- kernel/mem/paging.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 3c80bd22..a30222a5 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -166,6 +166,9 @@ static inline void px_set_page_dir(size_t page_dir) { static inline void px_paging_enable() { size_t cr0; asm volatile("mov %%cr0, %0": "=b"(cr0)); + // 0x80000000 = 0b10000000000000000000000000000000 + // The most significant bit signifies whether to + // enable or disable paging within control register 0. cr0 |= 0x80000000; asm volatile("mov %0, %%cr0":: "b"(cr0)); } @@ -173,6 +176,11 @@ static inline void px_paging_enable() { static inline void px_paging_disable() { size_t cr0; asm volatile("mov %%cr0, %0": "=b"(cr0)); + // 0x80000000 = 0b10000000000000000000000000000000 + // The most significant bit signifies whether to + // enable or disable paging within control register 0. + // In this case we set the opposite (~) so the result + // is 0b01111111111111111111111111111111 cr0 &= ~(0x80000000U); asm volatile("mov %0, %%cr0":: "b"(cr0)); } From 9098d797d882576aca7299224d3482863fc9fb60 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 28 Aug 2020 21:36:51 -0400 Subject: [PATCH 006/139] Removed usermode code It was taken from Toaru, so I don't want to keep it without attribution --- kernel/arch/i386/usermode.s | 61 ------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 kernel/arch/i386/usermode.s diff --git a/kernel/arch/i386/usermode.s b/kernel/arch/i386/usermode.s deleted file mode 100644 index 3f525004..00000000 --- a/kernel/arch/i386/usermode.s +++ /dev/null @@ -1,61 +0,0 @@ -/* Return to Userspace (from thread creation) */ - -.global return_to_userspace - -return_to_userspace: - pop %gs - pop %fs - pop %es - pop %ds - popa - add $8, %esp - iret - -/* Enter userspace (ring3) */ -.global jump_usermode - -.set MAGIC, 0xDECADE21 - -jump_usermode: - pushl %ebp - mov %esp, %ebp - mov 0xC(%ebp), %edx - mov %edx, %esp - pushl $MAGIC - - /* Segement selector */ - mov $0x23,%ax - - /* Save segement registers */ - mov %eax, %ds - mov %eax, %es - mov %eax, %fs - mov %eax, %gs - /* %ss is handled by iret */ - - /* Store stack address in %eax */ - mov %esp, %eax - - /* Data segmenet with bottom 2 bits set for ring3 */ - pushl $0x23 - - /* Push the stack address */ - pushl %eax - - /* Push flags and fix interrupt flag */ - pushf - popl %eax - - /* Request ring3 */ - orl $0x200, %eax - pushl %eax - pushl $0x1B - - /* Push entry point */ - pushl 0x8(%ebp) - - iret - # TODO: This iret need to be an iretq when in long mode - popl %ebp - ret - \ No newline at end of file From 406502d400b4a505ba52d91d82dc6e01294b07b0 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 28 Aug 2020 22:53:58 -0400 Subject: [PATCH 007/139] Wrote headers and empty functions for semaphores --- kernel/lib/semaphore.cpp | 42 +++++++++ sysroot/usr/include/kernel/lib/semaphore.hpp | 94 ++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 kernel/lib/semaphore.cpp create mode 100644 sysroot/usr/include/kernel/lib/semaphore.hpp diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp new file mode 100644 index 00000000..820af546 --- /dev/null +++ b/kernel/lib/semaphore.cpp @@ -0,0 +1,42 @@ +/** + * @file semaphore.cpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-28 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +// https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/_005f_005fatomic-Builtins.html + +#include + +int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { + +} + +int px_sem_wait(px_sem_t *sem) { + +} + +int sem_trywait(px_sem_t *sem) { + +} + +int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { + +} + +int px_sem_post(px_sem_t *sem) { + +} + +int px_sem_getval(px_sem_t *sem, uint32_t *val) { + +} + +int px_sem_destroy(px_sem_t *sem) { + +} \ No newline at end of file diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp new file mode 100644 index 00000000..1f854912 --- /dev/null +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -0,0 +1,94 @@ +/** + * @file semaphore.hpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-28 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#include + +typedef struct px_semaphore +{ + bool shared; + uint32_t count; +} px_sem_t; + +/** + * @brief Initializes a semaphore struct using the values + * defined. Semaphores are used in order to maintain mutual + * exclusion when multiple threads need to access a particular + * variable. + * + * @param sem Pointer to the semaphore structure to be used. + * @param shared Boolean value indicating whether the semaphore + * will be shared amongst threads or will be used within one thread + * exclusively. + * @param value Initialized value (how many times must the semaphore + * be accessed at the beginning before locking?) + * @return int Returns 0 if the semaphore was initialized successfully. + */ +int px_sem_init(px_sem_t *sem, bool shared, uint32_t value); +/** + * @brief Waiting on a semaphore decrements the count value. When a + * count value is 0, the semaphore is locked and the process or thread + * must sleep and wait until the semaphore is unlocked by calling post. + * + * @param sem Reference semaphore + * @return int Returns 0 on success and -1 on failure + * When an error occurs errno is set. + */ +int px_sem_wait(px_sem_t *sem); +/** + * @brief Functionally the same as px_sem_wait except that instead of + * blocking when the semaphore is locked, errno is set instead. + * + * @param sem Reference semaphore + * @return int Returns 0 on success and -1 on failure. + * When an error occurs errno is set. + */ +int sem_trywait(px_sem_t *sem); +/** + * @brief Functionally the same as px_sem_wait but with a timeout. This + * timeout does not mean that within the given period of time the + * semaphore will be unlocked but rather that after the timeout period + * the thread or process will unblock and may resume execution without + * access to the semaphore's reference variable. + * + * @param sem Reference semaphore + * @param usec Microseconds to wait until resuming execution without + * access to the semaphore's intended reference variable. + * @return int Returns 0 on success and -1 on failure. + * When an error occurs errno is set. + */ +int sem_timedwait(px_sem_t *sem, const uint32_t *usec); +/** + * @brief Increments the semaphore's counter. This is used to indicate + * that the thread or process is done utilizing the reference variable + * and that it is available for use. + * + * @param sem Reference semaphore + * @return int Returns 0 on success and -1 on failure. + * When an error occurs errno is set. + */ +int px_sem_post(px_sem_t *sem); +/** + * @brief Gets the counter value from a semaphore structure. + * + * @param sem Reference semaphore + * @param val + * @return int Returns 0 on success and -1 on failure. + * When an error occurs errno is set. + */ +int px_sem_getval(px_sem_t *sem, uint32_t *val); +/** + * @brief Destroys a semaphore by removing it from memory. + * + * @param sem Reference semaphore + * @return int Returns 0 on success and -1 on failure. + * When an error occurs errno is set. + */ +int px_sem_destroy(px_sem_t *sem); From fd0e62c0a8a22e0c476f10e234ab5cf677c89a20 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 29 Aug 2020 18:43:57 -0500 Subject: [PATCH 008/139] Add NASM support (again) --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b688c645..4f059691 100755 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include ATT_SRC = $(shell find kernel -name "*.s") +NASM_SRC = $(shell find kernel -name "*.S") CPP_SRC = $(shell find kernel -name "*.cpp") HEADERS = $(shell find $(INCLUDE) -name "*.hpp" -name "*.h") @@ -41,6 +42,7 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # Compilers/Assemblers/Linkers AS = $(shell command -v i686-elf-as) +NASM = $(shell command -v nasm) CXX = $(shell command -v i686-elf-gcc) LD = $(shell command -v i686-elf-ld) OBJCP = $(shell command -v i686-elf-objcopy) @@ -81,7 +83,8 @@ LD_FLAGS = -m elf_i386 \ # All objects OBJ = $(patsubst kernel/%.cpp, obj/%.o, $(CPP_SRC)) \ - $(patsubst kernel/%.s, obj/%.o, $(ATT_SRC)) + $(patsubst kernel/%.s, obj/%.o, $(ATT_SRC)) \ + $(patsubst kernel/%.S, obj/%.o, $(NASM_SRC)) # Object directories, mirroring source OBJ_DIRS = $(subst kernel, obj, $(shell find kernel -type d)) @@ -100,6 +103,10 @@ obj/%.o: kernel/%.s $(MAKE) mkdir_obj_dirs $(AS) $(AS_FLAGS) -o $@ $< +obj/%.o: kernel/%.S + $(MAKE) mkdir_obj_dirs + $(NASM) -felf -o $@ $< + # Kernel object dist/kernel: $(OBJ) @ mkdir -p dist From 94b025b33d0bf09fb168dfe086d33498558c55af Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 16:15:05 -0400 Subject: [PATCH 009/139] Finished rough draft of semaphore code (untested) --- kernel/lib/semaphore.cpp | 107 +++++++++++++++++-- sysroot/usr/include/kernel/lib/semaphore.hpp | 2 +- 2 files changed, 99 insertions(+), 10 deletions(-) diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 820af546..addcca3d 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -12,31 +12,120 @@ // https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/_005f_005fatomic-Builtins.html #include +#include +#include +#include int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { - + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + __atomic_store_n(&sem->count, value, __ATOMIC_RELEASE); + __atomic_store_n(&sem->shared, shared, __ATOMIC_RELEASE); } int px_sem_wait(px_sem_t *sem) { - + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + // Used to store the current value of the semaphore for atomic comparison later. + uint32_t curVal = sem->count; + // Compare the semaphore's current value to the value recorded earlier. + // If the semaphore counter is already 0 then just skip the compare and exhange. + do + { + while (curVal == 0) + { + curVal = sem->count; + } + // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. + } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); } int sem_trywait(px_sem_t *sem) { - + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + // Used to store the current value of the semaphore for atomic comparison later. + uint32_t curVal = sem->count; + // Compare the semaphore's current value to the value recorded earlier. + // If the semaphore counter is already 0 then just skip the compare and exhange. + do + { + // If the value is 0 then go ahead and return after setting errno. + if (curVal == 0) + { + // Set errno and return 0. + errno = EAGAIN; + return -1; + } + // We need to fail on an Atomic Acquire Release because it will fail less often (i.e. fewer loop iterations) + } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_ACQ_REL)); + // To get here the semaphore must not have been locked. + return 0; } int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { - + // TODO: Add the timer functionality here. + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + // Used to store the current value of the semaphore for atomic comparison later. + uint32_t curVal = sem->count; + // Compare the semaphore's current value to the value recorded earlier. + // If the semaphore counter is already 0 then just skip the compare and exhange. + do + { + while (curVal == 0) + { + curVal = sem->count; + } + // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. + } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); } int px_sem_post(px_sem_t *sem) { - + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + __atomic_fetch_add(&sem->count, 1, __ATOMIC_RELEASE); + return 0; } -int px_sem_getval(px_sem_t *sem, uint32_t *val) { - +uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val) { + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + uint32_t count = -1; + __atomic_load (&sem->count, &count, __ATOMIC_RELEASE); + return count; } int px_sem_destroy(px_sem_t *sem) { - -} \ No newline at end of file + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + free(sem); + return 0; +} diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index 1f854912..feea671d 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -83,7 +83,7 @@ int px_sem_post(px_sem_t *sem); * @return int Returns 0 on success and -1 on failure. * When an error occurs errno is set. */ -int px_sem_getval(px_sem_t *sem, uint32_t *val); +uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val); /** * @brief Destroys a semaphore by removing it from memory. * From a2bf72557acd265c7de0bbb5e8e3d2e3d3c20ece Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 16:49:21 -0400 Subject: [PATCH 010/139] Added mutex code --- kernel/lib/mutex.cpp | 100 +++++++++++++++++++++++ kernel/lib/semaphore.cpp | 34 +++++--- sysroot/usr/include/kernel/lib/mutex.hpp | 55 +++++++++++++ 3 files changed, 178 insertions(+), 11 deletions(-) create mode 100644 kernel/lib/mutex.cpp create mode 100644 sysroot/usr/include/kernel/lib/mutex.hpp diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp new file mode 100644 index 00000000..5f68fd32 --- /dev/null +++ b/kernel/lib/mutex.cpp @@ -0,0 +1,100 @@ +/** + * @file mutex.cpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-30 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +// All of the GCC builtin functions used here are documented at the link provided +// below. These builtins effectly generate assembly that will atomically perform +// the function described by the function name. Normally there would be a wrapper +// around these provided by but we can't use that since we don't have +// a standard library for either C or C++; +// +// Reference: +// https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/_005f_005fatomic-Builtins.html + +#include +#include +#include +#include + +int px_mutex_init(px_mutex_t *mutex) { + // Check if the mutex is valid + if (mutex == NULL) + { + errno = EINVAL; + return -1; + } + // Initialize the value to false + __atomic_store_n(&mutex->locked, false, __ATOMIC_RELEASE); + // Success, return 0 + return 0; +} + +int px_mutex_destroy(px_mutex_t *mutex) { + // Check if the mutex is valid + if (mutex == NULL) + { + errno = EINVAL; + return -1; + } + free(mutex); + // Success, return 0 + return 0; +} + +int px_mutex_lock(px_mutex_t *mutex) { + // Check if the mutex is valid + if (mutex == NULL) + { + errno = EINVAL; + return -1; + } + if (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) + { + return 0; + } + // If we did not get the lock then return -1. + return -1; +} + +int px_mutex_trylock(px_mutex_t *mutex) { + // Check if the mutex is valid + if (mutex == NULL) + { + errno = EINVAL; + return -1; + } + // Used to store the current value of the semaphore for atomic comparison later. + bool locked = mutex->locked; + // Compare the semaphore's current value to the value recorded earlier. + // If the semaphore counter is already 0 then just skip the compare and exhange. + do + { + while (locked == true) + { + locked = mutex->locked; + } + // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. + } while(!__atomic_compare_exchange_n(&mutex->locked, &locked, false, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); + // Success, return 0 + return 0; +} + +int px_mutex_unlock(px_mutex_t *mutex) { + // Check if the mutex is valid + if (mutex == NULL) + { + errno = EINVAL; + return -1; + } + // Clear the lock if it is locked + __atomic_clear(&mutex->locked, __ATOMIC_RELEASE); + // Success, return 0 + return 0; +} \ No newline at end of file diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index addcca3d..30e808ea 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -9,6 +9,13 @@ * */ +// All of the GCC builtin functions used here are documented at the link provided +// below. These builtins effectly generate assembly that will atomically perform +// the function described by the function name. Normally there would be a wrapper +// around these provided by but we can't use that since we don't have +// a standard library for either C or C++; +// +// Reference: // https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/_005f_005fatomic-Builtins.html #include @@ -25,6 +32,18 @@ int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { } __atomic_store_n(&sem->count, value, __ATOMIC_RELEASE); __atomic_store_n(&sem->shared, shared, __ATOMIC_RELEASE); + return 0; +} + +int px_sem_destroy(px_sem_t *sem) { + // Check if the semaphore is valid + if (sem == NULL) + { + errno = EINVAL; + return -1; + } + free(sem); + return 0; } int px_sem_wait(px_sem_t *sem) { @@ -46,6 +65,8 @@ int px_sem_wait(px_sem_t *sem) { } // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); + // Return success + return 0; } int sem_trywait(px_sem_t *sem) { @@ -94,6 +115,8 @@ int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { } // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); + // Return success + return 0; } int px_sem_post(px_sem_t *sem) { @@ -118,14 +141,3 @@ uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val) { __atomic_load (&sem->count, &count, __ATOMIC_RELEASE); return count; } - -int px_sem_destroy(px_sem_t *sem) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } - free(sem); - return 0; -} diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp new file mode 100644 index 00000000..f7e0d123 --- /dev/null +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -0,0 +1,55 @@ +/** + * @file mutex.hpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-30 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + + +#include + +typedef struct px_mutex { + bool locked; +} px_mutex_t; + +/** + * @brief Initializes a mutex for further use. + * + * @param mutex Reference mutex + * @return int Returns 0 on success and -1 on error. + */ +int px_mutex_init(px_mutex_t *mutex); +/** + * @brief Destroys a mutex and removes it from memory. + * + * @param mutex Reference mutex + * @return int Returns 0 on success and -1 on error. + */ +int px_mutex_destroy(px_mutex_t *mutex); +/** + * @brief Locks a provided mutex. + * + * @param mutex Reference mutex + * @return int Returns 0 on success and -1 on error. + */ +int px_mutex_lock(px_mutex_t *mutex); +/** + * @brief Waits for a mutex to become unlocked and then + * locks the mutex for use within whatever context this + * is called. + * + * @param mutex Reference mutex + * @return int Returns 0 on success and -1 on error. + */ +int px_mutex_trylock(px_mutex_t *mutex); +/** + * @brief Unlocks a mutex for others to use. + * + * @param mutex Reference mutex + * @return int Returns 0 on success and -1 on error. + */ +int px_mutex_unlock(px_mutex_t *mutex); \ No newline at end of file From ddc07b7ea3d63ff17e45cbfb6e1f054cf19dfe29 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 16:57:58 -0400 Subject: [PATCH 011/139] Fixed errno and atomic strengths --- kernel/lib/errno.cpp | 15 +++++++++++++++ kernel/lib/semaphore.cpp | 4 ++-- sysroot/usr/include/kernel/lib/errno.h | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 kernel/lib/errno.cpp diff --git a/kernel/lib/errno.cpp b/kernel/lib/errno.cpp new file mode 100644 index 00000000..6a7e9fad --- /dev/null +++ b/kernel/lib/errno.cpp @@ -0,0 +1,15 @@ +/** + * @file errno.cpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-30 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#include + +// Declare the actual errno value +int errno; \ No newline at end of file diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 30e808ea..1e0af98a 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -90,7 +90,7 @@ int sem_trywait(px_sem_t *sem) { return -1; } // We need to fail on an Atomic Acquire Release because it will fail less often (i.e. fewer loop iterations) - } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_ACQ_REL)); + } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)); // To get here the semaphore must not have been locked. return 0; } @@ -114,7 +114,7 @@ int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { curVal = sem->count; } // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. - } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); + } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)); // Return success return 0; } diff --git a/sysroot/usr/include/kernel/lib/errno.h b/sysroot/usr/include/kernel/lib/errno.h index b091b653..06a79aa5 100644 --- a/sysroot/usr/include/kernel/lib/errno.h +++ b/sysroot/usr/include/kernel/lib/errno.h @@ -14,7 +14,7 @@ // This is currently not thread safe. // But we also don't have threads, so problem solved. -int errno; +extern int errno; /** * @brief POSIX Error number definitions. These definitions From 4a8ad31192afc264b089c79fe74f947c005c055f Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 17:04:27 -0400 Subject: [PATCH 012/139] Added newline to end of errno.cpp Added newline to end of mutex.cpp Added newline to mutex.hpp --- kernel/lib/errno.cpp | 2 +- kernel/lib/mutex.cpp | 2 +- sysroot/usr/include/kernel/lib/mutex.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/lib/errno.cpp b/kernel/lib/errno.cpp index 6a7e9fad..44764cc3 100644 --- a/kernel/lib/errno.cpp +++ b/kernel/lib/errno.cpp @@ -12,4 +12,4 @@ #include // Declare the actual errno value -int errno; \ No newline at end of file +int errno; diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 5f68fd32..dec99f9a 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -97,4 +97,4 @@ int px_mutex_unlock(px_mutex_t *mutex) { __atomic_clear(&mutex->locked, __ATOMIC_RELEASE); // Success, return 0 return 0; -} \ No newline at end of file +} diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index f7e0d123..4055c9bf 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -52,4 +52,4 @@ int px_mutex_trylock(px_mutex_t *mutex); * @param mutex Reference mutex * @return int Returns 0 on success and -1 on error. */ -int px_mutex_unlock(px_mutex_t *mutex); \ No newline at end of file +int px_mutex_unlock(px_mutex_t *mutex); From 68cc8d139792c70ce7520637180d9542ae2de985 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 17:13:27 -0400 Subject: [PATCH 013/139] Fixed mutex_lock and inits for semaphores and mutexes --- kernel/lib/mutex.cpp | 10 +++++----- kernel/lib/semaphore.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index dec99f9a..23aee3f8 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -31,7 +31,7 @@ int px_mutex_init(px_mutex_t *mutex) { return -1; } // Initialize the value to false - __atomic_store_n(&mutex->locked, false, __ATOMIC_RELEASE); + mutex->locked = false; // Success, return 0 return 0; } @@ -55,12 +55,12 @@ int px_mutex_lock(px_mutex_t *mutex) { errno = EINVAL; return -1; } - if (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) + while (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) { - return 0; + // Busy wait while trying to get the lock } - // If we did not get the lock then return -1. - return -1; + // Success, return 0 + return 0; } int px_mutex_trylock(px_mutex_t *mutex) { diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 1e0af98a..8a4745c0 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -30,8 +30,8 @@ int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { errno = EINVAL; return -1; } - __atomic_store_n(&sem->count, value, __ATOMIC_RELEASE); - __atomic_store_n(&sem->shared, shared, __ATOMIC_RELEASE); + sem->count = value; + sem->shared = shared; return 0; } From e5640b07ef4c2bb81ad101b632ea113aef127197 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 17:15:53 -0400 Subject: [PATCH 014/139] Fixed trylock --- kernel/lib/mutex.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 23aee3f8..4a82ac6b 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -74,14 +74,11 @@ int px_mutex_trylock(px_mutex_t *mutex) { bool locked = mutex->locked; // Compare the semaphore's current value to the value recorded earlier. // If the semaphore counter is already 0 then just skip the compare and exhange. - do + if (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) { - while (locked == true) - { - locked = mutex->locked; - } - // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. - } while(!__atomic_compare_exchange_n(&mutex->locked, &locked, false, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); + errno = EINVAL; + return -1; + } // Success, return 0 return 0; } From adea2197b334292f86db33ccc844b04c49ca08d4 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 30 Aug 2020 17:18:39 -0400 Subject: [PATCH 015/139] Fixed comments in mutex and semaphore load level --- kernel/lib/mutex.cpp | 6 ++---- kernel/lib/semaphore.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 4a82ac6b..1b84a5d1 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -55,6 +55,7 @@ int px_mutex_lock(px_mutex_t *mutex) { errno = EINVAL; return -1; } + // Check if the mutex is unlocked while (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) { // Busy wait while trying to get the lock @@ -70,10 +71,7 @@ int px_mutex_trylock(px_mutex_t *mutex) { errno = EINVAL; return -1; } - // Used to store the current value of the semaphore for atomic comparison later. - bool locked = mutex->locked; - // Compare the semaphore's current value to the value recorded earlier. - // If the semaphore counter is already 0 then just skip the compare and exhange. + // If we cannot immediately acquire the lock then just return an error if (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) { errno = EINVAL; diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 8a4745c0..a54503a8 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -138,6 +138,6 @@ uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val) { return -1; } uint32_t count = -1; - __atomic_load (&sem->count, &count, __ATOMIC_RELEASE); + __atomic_load(&sem->count, &count, __ATOMIC_ACQUIRE); return count; } From cc51c19f42c62db9234548ac33d8ba0bca3e3490 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 12 Sep 2020 20:02:39 -0400 Subject: [PATCH 016/139] Added circular buffer library --- kernel/lib/ring_buffer.cpp | 91 ++++++++++++++++ .../usr/include/kernel/lib/ring_buffer.hpp | 101 ++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 kernel/lib/ring_buffer.cpp create mode 100644 sysroot/usr/include/kernel/lib/ring_buffer.hpp diff --git a/kernel/lib/ring_buffer.cpp b/kernel/lib/ring_buffer.cpp new file mode 100644 index 00000000..1a41cf7d --- /dev/null +++ b/kernel/lib/ring_buffer.cpp @@ -0,0 +1,91 @@ +/** + * @file ring_buffer.cpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief A circular buffer is a buffer method where the same + * memory used to contain data is reused. Inserting and removing + * data is done in a queue-like fashion. + * @version 0.3 + * @date 2020-09-12 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#include +#include + +int px_ring_buffer_init(px_ring_buff_t* buff, int size) { + // Set the struct variables (set locations and size) + buff->size = size; + buff->head = 0; + buff->tail = 0; + buff->length = 0; + // Allocate the memory for our buffer + buff->data = (uint8_t *)malloc(sizeof(uint8_t) * size); +} + +int px_ring_buffer_destroy(px_ring_buff_t* buff) +{ + // Free our data buffer and set the struct to null + free(buff->data); + buff = NULL; +} + +int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte) { + int status = 0; + // Check if the buffer is full. If so, we can't enqueue. + if (px_ring_buffer_is_full(buff)) { + status = -1; + } else { + // Write the data at the write index + buff->data[buff->head] = byte; + buff->head = ((buff->head + 1) & (buff->size - 1)); + ++buff->length; + } + // Return the status code + return status; +} + +int px_ring_buffer_dequeue(px_ring_buff_t* buff, uint8_t* data) { + int status = 0; + // Check if the buffer is empty. If so, we can't dequeue + if (px_ring_buffer_is_empty(buff)) { + status = -1; + } else { + // Read out the data and decrement the position + *data = buff->data[buff->tail]; + buff->tail = ((buff->tail + 1) & (buff->size - 1)); + --buff->length; + } + // Return the status code + return status; +} + +int px_ring_buffer_peek(px_ring_buff_t* buff, uint8_t* data) { + int status = 0; + // Check if the buffer is empty. If so, we can't dequeue + if (px_ring_buffer_is_empty(buff)) { + status = -1; + } else { + // Read out the data and don't decrement the position + *data = buff->data[buff->tail]; + } + // Return the status code + return status; +} + +bool px_ring_buffer_is_empty(px_ring_buff_t* buff) { + return (buff->length == 0); +} + +bool px_ring_buffer_is_full(px_ring_buff_t* buff) { + return (buff->length == buff->size); +} + +int px_ring_buffer_length(px_ring_buff_t* buff) { + return buff->length; +} + +int px_ring_buffer_size(px_ring_buff_t* buff) { + return buff->size; +} diff --git a/sysroot/usr/include/kernel/lib/ring_buffer.hpp b/sysroot/usr/include/kernel/lib/ring_buffer.hpp new file mode 100644 index 00000000..50e3dd19 --- /dev/null +++ b/sysroot/usr/include/kernel/lib/ring_buffer.hpp @@ -0,0 +1,101 @@ +/** + * @file ring_buffer.hpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief A circular buffer is a buffer method where the same + * memory used to contain data is reused. Inserting and removing + * data is done in a queue-like fashion. + * @version 0.3 + * @date 2020-09-12 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#ifndef PX_RING_BUFFER_HPP +#define PX_RING_BUFFER_HPP + +#include + +typedef struct px_ring_buff { + uint8_t* data; + int head; + int tail; + int size; + int length; +} px_ring_buff_t; + +/** + * @brief Initializes the circular buffer and allocates + * the data memory. + * + * @param buff Reference circular buffer + * @param size Maximum buffer capacity (in bytes) + * @return int Returns 0 on success and -1 on error. + */ +int px_ring_buffer_init(px_ring_buff_t* buff, int size); +/** + * @brief Destroys a circular buffer and frees all the + * data memory. + * + * @param buff Reference circular buffer + * @return int Returns 0 on success and -1 on error. + */ +int px_ring_buffer_destroy(px_ring_buff_t* buff); +/** + * @brief Writes a byte into the circular buffer. + * + * @param buff Reference circular buffer + * @param byte Byte to write to the buffer + * @return int Returns 0 on success and -1 on error. + */ +int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte); +/** + * @brief Removes a bytes from the circular buffer and writes + * the value of the byte to the data pointer. + * + * @param buff Reference circular buffer + * @param data Pointer to uint8_t to contain the data + * @return int Returns 0 on success and -1 on error. + */ +int px_ring_buffer_dequeue(px_ring_buff_t* buff, uint8_t* data); +/** + * @brief Grab the latest bytes of data from the buffer without + * removing it. + * + * @param buff Reference circular buffer + * @param data Pointer to uint8_t to contain the data + * @return int Returns 0 on success and -1 on error. + */ +int px_ring_buffer_peek(px_ring_buff_t* buff, uint8_t* data); +/** + * @brief Query whether the circular buffer is empty. + * + * @param buff Reference circular buffer + * @return true The buffer is empty + * @return false The buffer is not empty + */ +bool px_ring_buffer_is_empty(px_ring_buff_t* buff); +/** + * @brief Query whether the circular buffer is full. + * + * @param buff Reference circular buffer + * @return true The buffer is full + * @return false The buffer is not full + */ +bool px_ring_buffer_is_full(px_ring_buff_t* buff); +/** + * @brief Returns the number of items (bytes) in the buffer. + * + * @param buff Reference circular buffer + * @return int Number of bytes available for reading. + */ +int px_ring_buffer_length(px_ring_buff_t* buff); +/** + * @brief Returns the buffer capacity (in number of bytes). + * + * @param buff Reference circular buffer + * @return int Buffer capacity in bytes + */ +int px_ring_buffer_size(px_ring_buff_t* buff); + +#endif /* PX_RING_BUFFER_HPP */ From dabe2f4071f825dc879b1750b0087edffdabe3ec Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 12 Sep 2020 20:24:29 -0400 Subject: [PATCH 017/139] Added errnos and null checks for ring buffer lib --- kernel/lib/ring_buffer.cpp | 117 +++++++++++++----- .../usr/include/kernel/lib/ring_buffer.hpp | 5 +- 2 files changed, 87 insertions(+), 35 deletions(-) diff --git a/kernel/lib/ring_buffer.cpp b/kernel/lib/ring_buffer.cpp index 1a41cf7d..16394fab 100644 --- a/kernel/lib/ring_buffer.cpp +++ b/kernel/lib/ring_buffer.cpp @@ -1,7 +1,7 @@ /** * @file ring_buffer.cpp * @author Keeton Feavel (keetonfeavel@cedarville.edu) - * @brief A circular buffer is a buffer method where the same + * @brief A ring buffer is a buffer method where the same * memory used to contain data is reused. Inserting and removing * data is done in a queue-like fashion. * @version 0.3 @@ -13,18 +13,33 @@ #include #include +#include int px_ring_buffer_init(px_ring_buff_t* buff, int size) { - // Set the struct variables (set locations and size) - buff->size = size; - buff->head = 0; - buff->tail = 0; - buff->length = 0; - // Allocate the memory for our buffer - buff->data = (uint8_t *)malloc(sizeof(uint8_t) * size); + int status = 0; + // Check if the pointer is valid + if (buff != NULL) { + // Set the struct variables (set locations and size) + buff->size = size; + buff->head = 0; + buff->tail = 0; + buff->length = 0; + // Allocate the memory for our buffer + buff->data = (uint8_t *)malloc(sizeof(uint8_t) * size); + // Did we actually allocate the data? + if (buff->data == NULL) { + status = -1; + errno = ENOMEM; + } + } else { + status = -1; + errno = EINVAL; + } + // Return our status code + return status; } -int px_ring_buffer_destroy(px_ring_buff_t* buff) +void px_ring_buffer_destroy(px_ring_buff_t* buff) { // Free our data buffer and set the struct to null free(buff->data); @@ -33,14 +48,20 @@ int px_ring_buffer_destroy(px_ring_buff_t* buff) int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte) { int status = 0; - // Check if the buffer is full. If so, we can't enqueue. - if (px_ring_buffer_is_full(buff)) { - status = -1; + if (buff != NULL) { + // Check if the buffer is full. If so, we can't enqueue. + if (px_ring_buffer_is_full(buff)) { + status = -1; + errno = ENOBUFS; + } else { + // Write the data at the write index + buff->data[buff->head] = byte; + buff->head = ((buff->head + 1) & (buff->size - 1)); + ++buff->length; + } } else { - // Write the data at the write index - buff->data[buff->head] = byte; - buff->head = ((buff->head + 1) & (buff->size - 1)); - ++buff->length; + status = -1; + errno = EINVAL; } // Return the status code return status; @@ -48,14 +69,20 @@ int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte) { int px_ring_buffer_dequeue(px_ring_buff_t* buff, uint8_t* data) { int status = 0; - // Check if the buffer is empty. If so, we can't dequeue - if (px_ring_buffer_is_empty(buff)) { - status = -1; + if (buff != NULL) { + // Check if the buffer is empty. If so, we can't dequeue + if (px_ring_buffer_is_empty(buff)) { + status = -1; + errno = EINVAL; + } else { + // Read out the data and decrement the position + *data = buff->data[buff->tail]; + buff->tail = ((buff->tail + 1) & (buff->size - 1)); + --buff->length; + } } else { - // Read out the data and decrement the position - *data = buff->data[buff->tail]; - buff->tail = ((buff->tail + 1) & (buff->size - 1)); - --buff->length; + status = -1; + errno = EINVAL; } // Return the status code return status; @@ -63,29 +90,55 @@ int px_ring_buffer_dequeue(px_ring_buff_t* buff, uint8_t* data) { int px_ring_buffer_peek(px_ring_buff_t* buff, uint8_t* data) { int status = 0; - // Check if the buffer is empty. If so, we can't dequeue - if (px_ring_buffer_is_empty(buff)) { - status = -1; + if (buff != NULL) { + // Check if the buffer is empty. If so, we can't dequeue + if (px_ring_buffer_is_empty(buff)) { + status = -1; + errno = EINVAL; + } else { + // Read out the data and don't decrement the position + *data = buff->data[buff->tail]; + } } else { - // Read out the data and don't decrement the position - *data = buff->data[buff->tail]; + status = -1; + errno = EINVAL; } // Return the status code return status; } bool px_ring_buffer_is_empty(px_ring_buff_t* buff) { - return (buff->length == 0); + if (buff != NULL) { + return (buff->length == 0); + } else { + errno = EINVAL; + return false; + } } bool px_ring_buffer_is_full(px_ring_buff_t* buff) { - return (buff->length == buff->size); + if (buff != NULL) { + return (buff->length == buff->size); + } else { + errno = EINVAL; + return false; + } } int px_ring_buffer_length(px_ring_buff_t* buff) { - return buff->length; + if (buff != NULL) { + return buff->length; + } else { + errno = EINVAL; + return false; + } } int px_ring_buffer_size(px_ring_buff_t* buff) { - return buff->size; + if (buff != NULL) { + return buff->size; + } else { + errno = EINVAL; + return false; + } } diff --git a/sysroot/usr/include/kernel/lib/ring_buffer.hpp b/sysroot/usr/include/kernel/lib/ring_buffer.hpp index 50e3dd19..fe26069e 100644 --- a/sysroot/usr/include/kernel/lib/ring_buffer.hpp +++ b/sysroot/usr/include/kernel/lib/ring_buffer.hpp @@ -1,7 +1,7 @@ /** * @file ring_buffer.hpp * @author Keeton Feavel (keetonfeavel@cedarville.edu) - * @brief A circular buffer is a buffer method where the same + * @brief A ring buffer is a buffer method where the same * memory used to contain data is reused. Inserting and removing * data is done in a queue-like fashion. * @version 0.3 @@ -40,13 +40,12 @@ int px_ring_buffer_init(px_ring_buff_t* buff, int size); * @param buff Reference circular buffer * @return int Returns 0 on success and -1 on error. */ -int px_ring_buffer_destroy(px_ring_buff_t* buff); +void px_ring_buffer_destroy(px_ring_buff_t* buff); /** * @brief Writes a byte into the circular buffer. * * @param buff Reference circular buffer * @param byte Byte to write to the buffer - * @return int Returns 0 on success and -1 on error. */ int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte); /** From 24c4e4cd74f99e28aa4598437a95850760c2206b Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sun, 13 Sep 2020 13:14:54 -0400 Subject: [PATCH 018/139] Added Micah Switzer to Panix License authors --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 748cc2cb..e5aeaecd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Keeton "Auxel" Feavel +Copyright (c) 2019 Keeton "Auxel" Feavel, Micah Switzer, & The Panix Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 0675ce400b18fcb7bffa4e1a9618204ccb6914f1 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 13 Sep 2020 13:33:13 -0400 Subject: [PATCH 019/139] Changed & operator to % and added null check --- kernel/lib/ring_buffer.cpp | 19 ++++++++++++------- .../usr/include/kernel/lib/ring_buffer.hpp | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/kernel/lib/ring_buffer.cpp b/kernel/lib/ring_buffer.cpp index 16394fab..6e5bdf42 100644 --- a/kernel/lib/ring_buffer.cpp +++ b/kernel/lib/ring_buffer.cpp @@ -39,11 +39,16 @@ int px_ring_buffer_init(px_ring_buff_t* buff, int size) { return status; } -void px_ring_buffer_destroy(px_ring_buff_t* buff) -{ - // Free our data buffer and set the struct to null - free(buff->data); - buff = NULL; +int px_ring_buffer_destroy(px_ring_buff_t* buff) { + int status = 0; + if (buff != NULL) { + // Free our data buffer and set the struct to null + free(buff->data); + buff = NULL; + } else { + status = -1; + } + return status; } int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte) { @@ -56,7 +61,7 @@ int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte) { } else { // Write the data at the write index buff->data[buff->head] = byte; - buff->head = ((buff->head + 1) & (buff->size - 1)); + buff->head = ((buff->head + 1) % (buff->size - 1)); ++buff->length; } } else { @@ -77,7 +82,7 @@ int px_ring_buffer_dequeue(px_ring_buff_t* buff, uint8_t* data) { } else { // Read out the data and decrement the position *data = buff->data[buff->tail]; - buff->tail = ((buff->tail + 1) & (buff->size - 1)); + buff->tail = ((buff->tail + 1) % (buff->size - 1)); --buff->length; } } else { diff --git a/sysroot/usr/include/kernel/lib/ring_buffer.hpp b/sysroot/usr/include/kernel/lib/ring_buffer.hpp index fe26069e..ea19693a 100644 --- a/sysroot/usr/include/kernel/lib/ring_buffer.hpp +++ b/sysroot/usr/include/kernel/lib/ring_buffer.hpp @@ -40,7 +40,7 @@ int px_ring_buffer_init(px_ring_buff_t* buff, int size); * @param buff Reference circular buffer * @return int Returns 0 on success and -1 on error. */ -void px_ring_buffer_destroy(px_ring_buff_t* buff); +int px_ring_buffer_destroy(px_ring_buff_t* buff); /** * @brief Writes a byte into the circular buffer. * From 413768fc12d599f8bf6882862175d9ad174e2ba0 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 13 Sep 2020 13:59:42 -0400 Subject: [PATCH 020/139] Set errno in destroy and fixed modulo logic --- kernel/lib/ring_buffer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/lib/ring_buffer.cpp b/kernel/lib/ring_buffer.cpp index 6e5bdf42..fa6f2343 100644 --- a/kernel/lib/ring_buffer.cpp +++ b/kernel/lib/ring_buffer.cpp @@ -47,6 +47,7 @@ int px_ring_buffer_destroy(px_ring_buff_t* buff) { buff = NULL; } else { status = -1; + errno = EINVAL; } return status; } @@ -61,7 +62,7 @@ int px_ring_buffer_enqueue(px_ring_buff_t* buff, uint8_t byte) { } else { // Write the data at the write index buff->data[buff->head] = byte; - buff->head = ((buff->head + 1) % (buff->size - 1)); + buff->head = ((buff->head + 1) % buff->size); ++buff->length; } } else { @@ -82,7 +83,7 @@ int px_ring_buffer_dequeue(px_ring_buff_t* buff, uint8_t* data) { } else { // Read out the data and decrement the position *data = buff->data[buff->tail]; - buff->tail = ((buff->tail + 1) % (buff->size - 1)); + buff->tail = ((buff->tail + 1) % buff->size); --buff->length; } } else { From 2811d6284f7108815262f95c3c8d1530ea94b128 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 13 Sep 2020 15:04:03 -0400 Subject: [PATCH 021/139] Added ring buffer for RS232 input --- kernel/arch/i386/isr.cpp | 3 ++- kernel/dev/serial/rs232.cpp | 27 ++++++++++++++++--- .../usr/include/kernel/dev/serial/rs232.hpp | 13 ++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/kernel/arch/i386/isr.cpp b/kernel/arch/i386/isr.cpp index 44e8b657..6efd1008 100644 --- a/kernel/arch/i386/isr.cpp +++ b/kernel/arch/i386/isr.cpp @@ -75,8 +75,9 @@ extern "C" void px_irq_handler(registers_t *regs) { px_set_indicator(VGA_Red); /* After every interrupt we need to send an EOI to the PICs * or they will not send another interrupt again */ - if (regs->int_num >= 40) + if (regs->int_num >= 40) { px_write_byte(0xA0, 0x20); /* slave */ + } px_write_byte(0x20, 0x20); /* master */ /* Handle the interrupt in a more modular way */ diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 129c1909..f7aac29c 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -11,8 +11,9 @@ #include #include +#include -char* lineBuffer[RS_232_BUF_SIZE]; +static px_ring_buff_t* read_buffer = NULL; uint8_t rs_232_line_index; uint16_t rs_232_port_base; @@ -48,11 +49,18 @@ void px_rs232_print(char* str) { } static void px_rs232_callback(registers_t *regs) { - char str[2] = { px_rs232_read_char(), '\0' }; - if (str[0] == '\r') { - px_rs232_print("\n"); + // Grab the input character + char in = px_rs232_read_char(); + // Change carriage returns to newlines + if (in == '\r') { + in = '\n'; } + // Create a string and print it so that the + // user can see what they're typing. + char str[2] = {in, '\0'}; px_rs232_print(str); + // Add the character to the circular buffer + px_ring_buffer_enqueue(read_buffer, (uint8_t)in); } void px_rs232_init(uint16_t com_id) { @@ -82,3 +90,14 @@ void px_rs232_init(uint16_t com_id) { "Panix Serial Output Debugger\n\n" ); } + +px_ring_buff_t* px_rs232_init_buffer(int size) { + // Allocate space for the input buffer + read_buffer = (px_ring_buff_t*)malloc(sizeof(px_ring_buff_t)); + // Initialize the ring buffer + if (px_ring_buffer_init(read_buffer, size) == 0) { + return read_buffer; + } else { + return NULL; + } +} diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index 20d9f5f9..42408e44 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -11,6 +11,7 @@ */ #include +#include #define RS_232_COM1 0x3F8 #define RS_232_COM2 0x2F8 @@ -44,4 +45,14 @@ void px_rs232_init(uint16_t com_id); * serial output. * @param str Input string to be printed. */ -void px_rs232_print(char* str); \ No newline at end of file +void px_rs232_print(char* str); + +/** + * @brief Initializes the serial input buffer and + * returns a pointer to said buffer if successful. + * + * @param size Buffer capacity (in bytes) + * @return px_ring_buff_t* Pointer to buffer. NULL + * if memory could not be allocated. + */ +px_ring_buff_t* px_rs232_init_buffer(int size); From ae33e318aa159cbe5e44a4c926d475414bd220d2 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Tue, 15 Sep 2020 21:38:30 -0400 Subject: [PATCH 022/139] Added RS232 helper functions --- kernel/dev/serial/rs232.cpp | 47 +++++++++++++++++-- kernel/main.cpp | 10 ++-- .../usr/include/kernel/dev/serial/rs232.hpp | 36 +++++++++++++- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index f7aac29c..0b6ca2a7 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -1,12 +1,12 @@ /** * @file rs232.cpp * @author Keeton Feavel (keetonfeavel@cedarville.edu) - * @brief + * @brief * @version 0.3 * @date 2020-06-29 - * + * * @copyright Copyright the Panix Contributors (c) 2020 - * + * */ #include @@ -101,3 +101,44 @@ px_ring_buff_t* px_rs232_init_buffer(int size) { return NULL; } } + +px_ring_buff_t* px_rs232_get_buffer() { + // Can return NULL. This is documented. + return read_buffer; +} + +char px_rs232_get_char() { + // Grab the last byte and convert to a char + uint8_t data; + px_ring_buffer_dequeue(read_buffer, &data); + return (char)data; +} + +char* px_rs232_get_str() { + int idx = 0; + char* str = (char*)malloc(sizeof(char) * 1024); + // Keep reading until the buffer is empty or + // a newline is read. + while (!px_ring_buffer_is_empty(read_buffer)) { + uint8_t byte; + px_ring_buffer_dequeue(read_buffer, &byte); + str[idx] = (char)byte; + ++idx; + // Break if it's a newline + if ((char)byte == '\n') { + break; + } + } + // Add the null terminator + str[idx] = '\0'; + // Return the string + return str; +} + +int px_rs232_close() { + int ret = -1; + if (read_buffer != NULL) { + ret = px_ring_buffer_destroy(read_buffer); + } + return ret; +} \ No newline at end of file diff --git a/kernel/main.cpp b/kernel/main.cpp index bb6e227b..87b1c5f7 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -71,7 +71,7 @@ extern "C" void px_call_constructors() { * stack protection. GCC will automatically write the * canary code and use this function as the handler * for when a smashed stack is detected. - * + * */ uintptr_t __stack_chk_guard = STACK_CHK_GUARD; extern "C" void __stack_chk_fail(void) @@ -98,6 +98,8 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma px_timer_init(1000); // Programmable Interrupt Timer (1ms) // Enable interrupts now that we're out of a critical area px_interrupts_enable(); + // Enable serial input + px_rs232_init_buffer(1024); // Print some info to show we did things right px_rtc_print(); // Get the CPU vendor and model data to print @@ -112,12 +114,12 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma px_rs232_print("\n"); px_rs232_print(model); px_rs232_print("\n"); - + // Done px_kprintf(DBG_OKAY "Done.\n"); - + // Now that we're done make a joyful noise px_kernel_boot_tone(); - + // Keep the kernel alive. px_kprintf("\n"); int i = 0; diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index 42408e44..4cef416e 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -50,9 +50,43 @@ void px_rs232_print(char* str); /** * @brief Initializes the serial input buffer and * returns a pointer to said buffer if successful. - * + * * @param size Buffer capacity (in bytes) * @return px_ring_buff_t* Pointer to buffer. NULL * if memory could not be allocated. */ px_ring_buff_t* px_rs232_init_buffer(int size); + +/** + * @brief Returns the pointer to the RS232 input + * buffer. + * + * @return px_ring_buff_t* Ring buffer pointer + */ +px_ring_buff_t* px_rs232_get_buffer(); + +/** + * @brief Returns the most recently received byte + * from the serial input. + * @return char Character representation of latest + * buffer byte. + */ +char px_rs232_get_char(); + +/** + * @brief Returns all of the characters within the + * input buffer up until a newline or a null terminator. + * + * @return char* String read in from serial input. Needs + * to be freed later. + */ +char* px_rs232_get_str(); + +/** + * @brief Closes the serial input buffer and frees all of + * the data contained within. + * + * @return int Returns 0 on success and -1 on error. Errno + * is set appropriately. + */ +int px_rs232_close(); \ No newline at end of file From 24b35b32dff744329ab3b810627a17a608b6c7cb Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Tue, 15 Sep 2020 21:47:26 -0400 Subject: [PATCH 023/139] Added newline to end of header --- sysroot/usr/include/kernel/dev/serial/rs232.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index 4cef416e..fa3561e1 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -89,4 +89,4 @@ char* px_rs232_get_str(); * @return int Returns 0 on success and -1 on error. Errno * is set appropriately. */ -int px_rs232_close(); \ No newline at end of file +int px_rs232_close(); From e768678bdfd1e3aa6d8e84acc79a0a6d36c80a7b Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Thu, 17 Sep 2020 22:28:33 -0400 Subject: [PATCH 024/139] get_str now requires buffer and max size Also stops on null terminator and sets null terminator properly --- kernel/dev/serial/rs232.cpp | 18 +++++++++++------- .../usr/include/kernel/dev/serial/rs232.hpp | 9 +++++---- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 0b6ca2a7..89149619 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -114,9 +114,8 @@ char px_rs232_get_char() { return (char)data; } -char* px_rs232_get_str() { +int px_rs232_get_str(char* str, int max) { int idx = 0; - char* str = (char*)malloc(sizeof(char) * 1024); // Keep reading until the buffer is empty or // a newline is read. while (!px_ring_buffer_is_empty(read_buffer)) { @@ -124,21 +123,26 @@ char* px_rs232_get_str() { px_ring_buffer_dequeue(read_buffer, &byte); str[idx] = (char)byte; ++idx; - // Break if it's a newline - if ((char)byte == '\n') { + // Break if it's a newline or null + if ((char)byte == '\n' + || byte == 0 + || idx == (max - 1)) + { + // Add the null terminator + str[idx] = '\0'; + ++idx; break; } } - // Add the null terminator - str[idx] = '\0'; // Return the string - return str; + return idx; } int px_rs232_close() { int ret = -1; if (read_buffer != NULL) { ret = px_ring_buffer_destroy(read_buffer); + read_buffer = NULL; } return ret; } \ No newline at end of file diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index fa3561e1..a74b9005 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -76,11 +76,12 @@ char px_rs232_get_char(); /** * @brief Returns all of the characters within the * input buffer up until a newline or a null terminator. - * - * @return char* String read in from serial input. Needs - * to be freed later. + * + * @param str Character buffer to hold the serial input + * @param max Max number of characters to read in + * @return char* Returns the number of characters read. */ -char* px_rs232_get_str(); +int px_rs232_get_str(char* str, int max); /** * @brief Closes the serial input buffer and frees all of From 253133be9cc41cb10082b74be13e6c7ce653d3d8 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 18 Sep 2020 22:03:37 -0400 Subject: [PATCH 025/139] Fixed undefined behaviour for get char --- kernel/dev/serial/rs232.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 89149619..922dbc3c 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -109,8 +109,11 @@ px_ring_buff_t* px_rs232_get_buffer() { char px_rs232_get_char() { // Grab the last byte and convert to a char - uint8_t data; - px_ring_buffer_dequeue(read_buffer, &data); + uint8_t data = 0; + if (read_buffer != NULL) + { + px_ring_buffer_dequeue(read_buffer, &data); + } return (char)data; } From f2161559d93ddb55657365ef986a42bb727f19fe Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 28 Sep 2020 19:37:46 -0400 Subject: [PATCH 026/139] Add note about reliability of rs232 driver --- kernel/dev/serial/rs232.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 922dbc3c..0b627e0e 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -7,6 +7,9 @@ * * @copyright Copyright the Panix Contributors (c) 2020 * + * TODO: Make this module robust enough for fast transmission of binary data + * currently it adequately supports slow, character transmission. + * */ #include @@ -148,4 +151,4 @@ int px_rs232_close() { read_buffer = NULL; } return ret; -} \ No newline at end of file +} From 09333a05155899de6d02ab110a5a7ecd02c5d4e0 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Thu, 1 Oct 2020 19:38:08 -0400 Subject: [PATCH 027/139] Added -Wall and -Werror flags --- Makefile | 4 +++- kernel/dev/rtc/rtc.cpp | 17 +++++++---------- kernel/lib/bitmap.cpp | 6 ++++-- kernel/sys/panic.cpp | 1 - 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 4f059691..f9a66c32 100755 --- a/Makefile +++ b/Makefile @@ -67,7 +67,9 @@ CXXFLAGS = \ -fno-leading-underscore \ -fno-omit-frame-pointer \ -Wno-write-strings \ - -std=c++2a + -Wall \ + -Werror \ + -std=c++17 # C / C++ pre-processor flags CPP_FLAGS = \ -D VERSION=\"$(GIT_VERSION)\" diff --git a/kernel/dev/rtc/rtc.cpp b/kernel/dev/rtc/rtc.cpp index e8857ecf..cda11c94 100644 --- a/kernel/dev/rtc/rtc.cpp +++ b/kernel/dev/rtc/rtc.cpp @@ -62,7 +62,7 @@ uint8_t px_rtc_get_register(int reg) { void px_read_rtc() { // Previous values from RTC // Used as a cache to check if we should update - uint8_t century, last_second, last_minute, + uint8_t px_rtc_century, last_second, last_minute, last_hour, last_day, last_month, last_year, last_century, registerB; // Make sure an update isn't in progress @@ -74,15 +74,12 @@ void px_read_rtc() { px_rtc_day = px_rtc_get_register(0x07); px_rtc_month = px_rtc_get_register(0x08); px_rtc_year = px_rtc_get_register(0x09); - - if (RTC_CURRENT_CENTURY != 0) { - century = px_rtc_get_register(RTC_CURRENT_CENTURY); - } + px_rtc_century = px_rtc_get_register(RTC_CURRENT_CENTURY); while ((last_second != px_rtc_second) || (last_minute != px_rtc_minute) || (last_hour != px_rtc_hour) || (last_day != px_rtc_day) || (last_month != px_rtc_month) || (last_year != px_rtc_year) || - (last_century != century)) + (last_century != px_rtc_century)) { last_second = px_rtc_second; last_minute = px_rtc_minute; @@ -90,7 +87,7 @@ void px_read_rtc() { last_day = px_rtc_day; last_month = px_rtc_month; last_year = px_rtc_year; - last_century = century; + last_century = px_rtc_century; // Make sure an update isn't in progress while (px_rtc_get_update_in_progress()); @@ -102,7 +99,7 @@ void px_read_rtc() { px_rtc_month = px_rtc_get_register(0x08); px_rtc_year = px_rtc_get_register(0x09); if (RTC_CURRENT_CENTURY != 0) { - century = px_rtc_get_register(RTC_CURRENT_CENTURY); + px_rtc_century = px_rtc_get_register(RTC_CURRENT_CENTURY); } } @@ -118,7 +115,7 @@ void px_read_rtc() { px_rtc_year = (px_rtc_year & 0x0F) + ((px_rtc_year / 16) * 10); if (RTC_CURRENT_CENTURY != 0) { - century = (century & 0x0F) + ((century / 16) * 10); + px_rtc_century = (px_rtc_century & 0x0F) + ((px_rtc_century / 16) * 10); } } @@ -129,7 +126,7 @@ void px_read_rtc() { // Calculate the full (4-digit) year if(RTC_CURRENT_CENTURY != 0) { - px_rtc_year += century * 100; + px_rtc_year += px_rtc_century * 100; } else { px_rtc_year += (RTC_CURRENT_YEAR / 100) * 100; if(px_rtc_year < RTC_CURRENT_YEAR) px_rtc_year += 100; diff --git a/kernel/lib/bitmap.cpp b/kernel/lib/bitmap.cpp index bf415837..f3ea4540 100644 --- a/kernel/lib/bitmap.cpp +++ b/kernel/lib/bitmap.cpp @@ -5,7 +5,7 @@ #endif size_t bitmap_find_first_range_clear(bitmap_t *bitmap, size_t size, size_t count) { - size_t bm, check_lo, check_hi, check, masked, idx, ofst; + size_t check_lo, check_hi, check, masked, idx, ofst; size_t mask = ((size_t)1 << count) - (size_t)1; for (size_t i = 0UL; i < size - count; i++) { idx = INDEX_FROM_BIT(i); @@ -17,7 +17,9 @@ size_t bitmap_find_first_range_clear(bitmap_t *bitmap, size_t size, size_t count #ifdef TESTING printf("i = %d, idx = 0x%08x, ofst = 0x%08x, check_lo = 0x%08x, " "check_hi = 0x%08x, check = 0x%08x, masked = 0x%08x\n", - i, idx, ofst, check_lo, check_hi, check, masked); + i, idx, ofst, check_lo, check_hi, check, masked); +#else + (void)masked; #endif if (!(check & mask)) return i; } diff --git a/kernel/sys/panic.cpp b/kernel/sys/panic.cpp index d5222ec2..319de319 100644 --- a/kernel/sys/panic.cpp +++ b/kernel/sys/panic.cpp @@ -100,7 +100,6 @@ void panic(registers_t *regs, const char *file, uint32_t line, const char *func) int rw = regs->err_code & 0x2; // Write operation? int us = regs->err_code & 0x4; // Processor was in user-mode? int reserved = regs->err_code & 0x8; // Overwritten CPU-reserved bits of page entry? - int id = regs->err_code & 0x10; // Caused by an instruction fetch? // If we have a page fault, print out page fault info if (regs->int_num == 14) { // Output an error message. From 362f35490ec0cf45562630f2a69e39e189da4c38 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Thu, 1 Oct 2020 20:24:33 -0400 Subject: [PATCH 028/139] Resolved #128 code review issues --- kernel/lib/bitmap.cpp | 6 ++---- kernel/sys/panic.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/lib/bitmap.cpp b/kernel/lib/bitmap.cpp index f3ea4540..8f454946 100644 --- a/kernel/lib/bitmap.cpp +++ b/kernel/lib/bitmap.cpp @@ -5,7 +5,7 @@ #endif size_t bitmap_find_first_range_clear(bitmap_t *bitmap, size_t size, size_t count) { - size_t check_lo, check_hi, check, masked, idx, ofst; + size_t check_lo, check_hi, check, idx, ofst; size_t mask = ((size_t)1 << count) - (size_t)1; for (size_t i = 0UL; i < size - count; i++) { idx = INDEX_FROM_BIT(i); @@ -13,13 +13,11 @@ size_t bitmap_find_first_range_clear(bitmap_t *bitmap, size_t size, size_t count check_lo = bitmap[idx] >> ofst; check_hi = ofst ? bitmap[idx + 1] << (BITS_PER_BITMAP_T - ofst) : 0; check = check_lo | check_hi; - masked = check & mask; #ifdef TESTING + size_t masked = check & mask; printf("i = %d, idx = 0x%08x, ofst = 0x%08x, check_lo = 0x%08x, " "check_hi = 0x%08x, check = 0x%08x, masked = 0x%08x\n", i, idx, ofst, check_lo, check_hi, check, masked); -#else - (void)masked; #endif if (!(check & mask)) return i; } diff --git a/kernel/sys/panic.cpp b/kernel/sys/panic.cpp index 319de319..7879b254 100644 --- a/kernel/sys/panic.cpp +++ b/kernel/sys/panic.cpp @@ -100,6 +100,7 @@ void panic(registers_t *regs, const char *file, uint32_t line, const char *func) int rw = regs->err_code & 0x2; // Write operation? int us = regs->err_code & 0x4; // Processor was in user-mode? int reserved = regs->err_code & 0x8; // Overwritten CPU-reserved bits of page entry? + int id = regs->err_code & 0x10; // Caused by an instruction fetch? // If we have a page fault, print out page fault info if (regs->int_num == 14) { // Output an error message. @@ -111,12 +112,13 @@ void panic(registers_t *regs, const char *file, uint32_t line, const char *func) char msg[128]; px_ksprintf( msg, - "Page fault (%s%s%s%s) at 0x0x%08X\n", + "Page fault (%s%s%s%s) at 0x0x%08X (id -> %i)\n", real, rws, uss, avail, - faulting_address + faulting_address, + id ); // Print to VGA and serial px_kprintf("%s", msg); From 22317bb9d16a79a2114a6544fbf10cd73b1bd5bc Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Thu, 1 Oct 2020 21:04:35 -0400 Subject: [PATCH 029/139] Updated codefactor badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab46d109..b1503cb0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![CodeFactor](https://www.codefactor.io/repository/github/panix-os-dev-team/panix/badge)](https://www.codefactor.io/repository/github/panix-os-dev-team/panix) +[![CodeFactor](https://www.codefactor.io/repository/github/panix-os/panix/badge)](https://www.codefactor.io/repository/github/panix-os/panix) ![Logo](https://github.com/panix-os-dev-team/Documentation/blob/0ac31a6148eea4804a31684b13805542698c1239/logo.png?raw=true) ### Panix From acd54917a30bd3d009eb6b3a3c3c8f17912d47d4 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Thu, 1 Oct 2020 21:14:24 -0400 Subject: [PATCH 030/139] Updated README logo Deleting the docs repo got rid of the image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1503cb0..c7a243ae 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![CodeFactor](https://www.codefactor.io/repository/github/panix-os/panix/badge)](https://www.codefactor.io/repository/github/panix-os/panix) -![Logo](https://github.com/panix-os-dev-team/Documentation/blob/0ac31a6148eea4804a31684b13805542698c1239/logo.png?raw=true) +![Logo](https://github.com/panix-os/panix-os.github.io/blob/master/img/logo.png?raw=true) ### Panix Panix is a small, hobbyist kernel started by [Keeton Feavel](https://github.com/Kfeavel) and further developed with the help of [Micah Switzer](https://github.com/micahswitzer). Having now undergone three rewrites from the ground up, Panix has come a long way since its first start in 2018. From c84b82a33949f175fa98768286ba87d354f0d19c Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 2 Oct 2020 20:41:24 -0400 Subject: [PATCH 031/139] Added memory address check to the stack trace --- kernel/mem/paging.cpp | 6 +++++- kernel/sys/trace.cpp | 6 ++++++ sysroot/usr/include/kernel/lib/bitmap.hpp | 4 ++++ sysroot/usr/include/kernel/mem/paging.hpp | 9 +++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index a30222a5..61f0242d 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -207,7 +207,6 @@ void* px_get_new_page(uint32_t size) { for (uint32_t i = free_idx; i < free_idx + page_count; i++) { uint32_t phys_page_idx = find_next_free_phys_page(); if (phys_page_idx == SIZE_T_MAX_VALUE) return NULL; - // This line crashes on the 8th iteration of the stress test loop in main. px_map_kernel_page(VADDR((uint32_t)i * PAGE_SIZE), phys_page_idx * PAGE_SIZE); } return (void *)(free_idx * PAGE_SIZE); @@ -232,3 +231,8 @@ void px_free_page(void *page, uint32_t size) { } } +bool px_page_is_present(size_t addr) { + // Convert the address into an index and + // check whether the page is in the bitmap + return bitmap_get_bit(mapped_pages, (addr >> 12)); +} diff --git a/kernel/sys/trace.cpp b/kernel/sys/trace.cpp index f8d1fdff..5a7da94b 100644 --- a/kernel/sys/trace.cpp +++ b/kernel/sys/trace.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include void px_stack_trace(size_t max) { @@ -26,6 +27,11 @@ void px_stack_trace(size_t max) { px_ksprintf(buf, "0x%08X\n", stk->eip); px_kprintf("\033[%i;%iH %s", (frame + 1), (X86_TTY_WIDTH - 16), buf); px_rs232_print(buf); + // Check whether the address is in memory or not + if (!px_page_is_present((size_t)stk->ebp)) + { + break; + } stk = stk->ebp; } } \ No newline at end of file diff --git a/sysroot/usr/include/kernel/lib/bitmap.hpp b/sysroot/usr/include/kernel/lib/bitmap.hpp index 7ed47c56..d057ca44 100644 --- a/sysroot/usr/include/kernel/lib/bitmap.hpp +++ b/sysroot/usr/include/kernel/lib/bitmap.hpp @@ -36,6 +36,10 @@ static inline void bitmap_set_bit(bitmap_t *bitmap, size_t index) { SET_BIT_IN_MAP(bitmap, index); } +static inline bool bitmap_get_bit(bitmap_t *bitmap, size_t index) { + return ((bitmap)[INDEX_FROM_BIT((index))] >> OFFSET_FROM_BIT((index))) & 1; +} + static inline void bitmap_clear_bit(bitmap_t *bitmap, size_t index) { UNSET_BIT_IN_MAP(bitmap, index); } diff --git a/sysroot/usr/include/kernel/mem/paging.hpp b/sysroot/usr/include/kernel/mem/paging.hpp index a70bd220..60c34d8b 100644 --- a/sysroot/usr/include/kernel/mem/paging.hpp +++ b/sysroot/usr/include/kernel/mem/paging.hpp @@ -142,5 +142,14 @@ void* px_get_new_page(uint32_t size); */ void px_free_page(void *page, uint32_t size); +/** + * @brief Checks whether an address is mapped into memory. + * + * @param addr Address to be checked. + * @return true The address is mapped in and valid. + * @return false The address is not mapped into memory. + */ +bool px_page_is_present(size_t addr); + #endif /* PANIX_MEM_PAGING */ From 4ccfd72487bd7ab28e8210cd751c247d1ec9283c Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 3 Oct 2020 00:50:53 -0400 Subject: [PATCH 032/139] Changed compiler to Clang++ Any other changes were made to get the code to compile --- Makefile | 18 ++++++++++------- kernel/dev/rtc/rtc.cpp | 20 ++++++++++--------- kernel/dev/serial/rs232.cpp | 2 +- kernel/lib/string.cpp | 5 +++-- kernel/sys/panic.cpp | 4 ++-- .../usr/include/kernel/dev/serial/rs232.hpp | 2 +- sysroot/usr/include/kernel/sys/panic.hpp | 2 +- 7 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index f9a66c32..21ec1207 100755 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # Compilers/Assemblers/Linkers AS = $(shell command -v i686-elf-as) NASM = $(shell command -v nasm) -CXX = $(shell command -v i686-elf-gcc) +CXX = $(shell command -v clang++) LD = $(shell command -v i686-elf-ld) OBJCP = $(shell command -v i686-elf-objcopy) MKGRUB = $(shell command -v grub-mkrescue) @@ -51,24 +51,28 @@ MKGRUB = $(shell command -v grub-mkrescue) CFLAGS = \ -I ${SYSROOT}/usr/include/kernel/ # C++ only flags (-lgcc flag is used b/c it has helpful functions) +# Flags explained: +# +# -Wno-unused-function +# We need to ignore unused functions because we may use +# them at a later time. For example, paging disable. +# CXXFLAGS = \ - -m32 \ -g \ - -nostartfiles \ - -nodefaultlibs \ - -lgcc \ + -m32 \ + -target i386-none-elf \ -ffreestanding \ -fstack-protector-all \ -fpermissive \ + -nodefaultlibs \ -fno-use-cxa-atexit \ -fno-builtin \ -fno-rtti \ -fno-exceptions \ - -fno-leading-underscore \ -fno-omit-frame-pointer \ - -Wno-write-strings \ -Wall \ -Werror \ + -Wno-unused-function \ -std=c++17 # C / C++ pre-processor flags CPP_FLAGS = \ diff --git a/kernel/dev/rtc/rtc.cpp b/kernel/dev/rtc/rtc.cpp index cda11c94..1fa6ca28 100644 --- a/kernel/dev/rtc/rtc.cpp +++ b/kernel/dev/rtc/rtc.cpp @@ -17,12 +17,13 @@ void px_rtc_callback(registers_t *regs); // Current values from RTC -uint8_t px_rtc_second; // Current UTC second -uint8_t px_rtc_minute; // Current UTC minute -uint8_t px_rtc_hour; // Current UTC hour -uint8_t px_rtc_day; // Current UTC day (not reliable) -uint8_t px_rtc_month; // Current UTC month -uint32_t px_rtc_year; // Current UTC year +uint8_t px_rtc_second; // Current UTC second +uint8_t px_rtc_minute; // Current UTC minute +uint8_t px_rtc_hour; // Current UTC hour +uint8_t px_rtc_day; // Current UTC day (not reliable) +uint8_t px_rtc_month; // Current UTC month +uint32_t px_rtc_year; // Current UTC year +uint32_t px_rtc_century; // Current UTC century void px_rtc_init() { px_kprintf(DBG_INFO "Initializing RTC...\n"); @@ -62,9 +63,10 @@ uint8_t px_rtc_get_register(int reg) { void px_read_rtc() { // Previous values from RTC // Used as a cache to check if we should update - uint8_t px_rtc_century, last_second, last_minute, - last_hour, last_day, last_month, - last_year, last_century, registerB; + uint8_t last_second = 0, last_minute = 0, + last_hour = 0, last_day = 0, + last_month = 0, last_year = 0, + last_century = 0, registerB = 0; // Make sure an update isn't in progress while (px_rtc_get_update_in_progress()); diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 0b627e0e..805036d7 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -45,7 +45,7 @@ static void px_rs232_write_char(char c) { px_write_byte(rs_232_port_base + RS_232_DATA_REG, c); } -void px_rs232_print(char* str) { +void px_rs232_print(const char* str) { for (int i = 0; str[i] != 0; i++) { px_rs232_write_char(str[i]); } diff --git a/kernel/lib/string.cpp b/kernel/lib/string.cpp index 77f92fa3..748b64e7 100644 --- a/kernel/lib/string.cpp +++ b/kernel/lib/string.cpp @@ -10,6 +10,7 @@ */ #include +#include int strlen(const char* s) { int i = 0; @@ -19,11 +20,11 @@ int strlen(const char* s) { return i; } +//TODO: Fix this function. I don't think it works. char* strcat(const char *s1, const char *s2) { const size_t len1 = strlen(s1); const size_t len2 = strlen(s2); - char *result = ""; - // = malloc(len1 + len2 + 1); // +1 for the null-terminator + char *result = (char *)malloc(len1 + len2 + 1); // +1 for the null-terminator // in real code you would check for errors in malloc here memcpy(result, s1, len1); memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator diff --git a/kernel/sys/panic.cpp b/kernel/sys/panic.cpp index 7879b254..cb2d845f 100644 --- a/kernel/sys/panic.cpp +++ b/kernel/sys/panic.cpp @@ -23,7 +23,7 @@ void panic_print_register(registers_t *regs); void printPanicScreen(int exception) { px_tty_clear(VGA_Black, VGA_White); - char* tag; + const char* tag; if (exception == 13) { tag = "< Wait... That's Illegal >\n"; } else { @@ -47,7 +47,7 @@ void printPanicScreen(int exception) { px_rs232_print(cow); } -void panic(char* msg, const char *file, uint32_t line, const char *func) { +void panic(const char* msg, const char *file, uint32_t line, const char *func) { asm volatile ("cli"); // Print the panic cow printPanicScreen(0); diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index a74b9005..993c0d3b 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -45,7 +45,7 @@ void px_rs232_init(uint16_t com_id); * serial output. * @param str Input string to be printed. */ -void px_rs232_print(char* str); +void px_rs232_print(const char* str); /** * @brief Initializes the serial input buffer and diff --git a/sysroot/usr/include/kernel/sys/panic.hpp b/sysroot/usr/include/kernel/sys/panic.hpp index 07d38365..b8145efd 100644 --- a/sysroot/usr/include/kernel/sys/panic.hpp +++ b/sysroot/usr/include/kernel/sys/panic.hpp @@ -28,7 +28,7 @@ extern const char* px_exception_descriptions[]; * @param line Line with the error * @param func Function containing error */ -void panic(char* msg, const char *file, uint32_t line, const char *func); +void panic(const char* msg, const char *file, uint32_t line, const char *func); /** * @brief Halts kernel execution and prints register info. * From c55f38920e87a0bcae65ce657cc63033085dd383 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 3 Oct 2020 13:05:42 -0400 Subject: [PATCH 033/139] Updated nasm, linker, and objcopy to llvm / clang --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 21ec1207..7f542579 100755 --- a/Makefile +++ b/Makefile @@ -42,10 +42,10 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # Compilers/Assemblers/Linkers AS = $(shell command -v i686-elf-as) -NASM = $(shell command -v nasm) +NASM = $(shell command -v llc) CXX = $(shell command -v clang++) -LD = $(shell command -v i686-elf-ld) -OBJCP = $(shell command -v i686-elf-objcopy) +LD = $(shell command -v ld.lld) +OBJCP = $(shell command -v llvm-objcopy) MKGRUB = $(shell command -v grub-mkrescue) # C / C++ flags (include directory) CFLAGS = \ From 039d46875ea2b9b3dc94ce06541f2101ae81eab1 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Mon, 5 Oct 2020 23:39:44 -0400 Subject: [PATCH 034/139] Added debug and release targets --- Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f9a66c32..4de52491 100755 --- a/Makefile +++ b/Makefile @@ -115,6 +115,14 @@ dist/kernel: $(OBJ) $(LD) $(LD_FLAGS) -o $@ $(OBJ) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym +# Debug build +debug: CXXFLAGS += -DDEBUG +debug: CFLAGS += -DDEBUG +debug: dist/kernel + +# Release build +release: dist/kernel + # ******************************** # * Kernel Distribution Creation * # ******************************** @@ -168,8 +176,8 @@ vbox: vbox-create $(VBOX) startvm --putenv --debug $(VM_NAME) # Open the connection to qemu and load our kernel-object file with symbols -.PHONY: debug -debug: dist/kernel +.PHONY: debugger +debugger: dist/kernel # Start QEMU with debugger ($(QEMU) \ -S -s \ From 8841c8716389d3e4776c4cb94aeea27846a84a75 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Mon, 5 Oct 2020 23:39:54 -0400 Subject: [PATCH 035/139] Moved heap and paging logs into debug ifdefs --- kernel/mem/heap.cpp | 42 ++++++++++++++++++++++++++---------------- kernel/mem/paging.cpp | 24 +++++++++++++++--------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index 3ff5883b..da3b9586 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -35,19 +35,25 @@ px_heap_chunk_t* first = NULL; px_heap_chunk_t* last = NULL; void* slot[NUM_SLOTS] = { NULL }; +#if defined(DEBUG) char dbg_buf[64] = {0}; +#endif static void px_memory_chunk_init(px_heap_chunk_t* chunk) { - px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); +#if defined(DEBUG) + px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); px_rs232_print(dbg_buf); +#endif dlist_init(&chunk->all); chunk->used = 0; dlist_init(&chunk->free); } static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { - px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); +#if defined(DEBUG) + px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); px_rs232_print(dbg_buf); +#endif char* end = (char*)(chunk->all.next); char* start = (char*)(&chunk->all); return (end - start) - HEADER_SIZE; @@ -65,10 +71,10 @@ static int px_memory_chunk_slot(size_t size) { static void px_remove_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); - +#if defined(DEBUG) px_ksprintf(dbg_buf, "%s(0x%p) : removing chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); px_rs232_print(dbg_buf); - +#endif DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); mem_free -= len - HEADER_SIZE; } @@ -76,10 +82,10 @@ static void px_remove_free(px_heap_chunk_t* chunk) { static void px_push_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); - +#if defined(DEBUG) px_ksprintf(dbg_buf, "%s(0x%p) : adding chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); px_rs232_print(dbg_buf); - +#endif DLIST_PUSH(&free_chunk[n], chunk, free); mem_free += len - HEADER_SIZE; } @@ -128,10 +134,10 @@ void px_heap_init(size_t size) { // Get the sizes and number of chunks size_t len = px_memory_chunk_size(second); int n = px_memory_chunk_slot(len); - +#if defined(DEBUG) px_ksprintf(dbg_buf, "%s(0x%p, 0x%lx) : adding chunk 0x%lx [%d]\n", __FUNCTION__, mem, size, len, n); px_rs232_print(dbg_buf); - +#endif // Push them onto the linked list and update tracking variables DLIST_PUSH(&free_chunk[n], second, free); mem_free = len - HEADER_SIZE; @@ -139,9 +145,10 @@ void px_heap_init(size_t size) { } void* malloc(size_t size) { +#if defined(DEBUG) px_ksprintf(dbg_buf, "%s(0x%lx)\n", __FUNCTION__, size); px_rs232_print(dbg_buf); - +#endif size = (size + ALIGN - 1) & (~(ALIGN - 1)); if (size < MIN_SIZE) { @@ -161,10 +168,10 @@ void* malloc(size_t size) { px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); size_t size2 = px_memory_chunk_size(chunk); - +#if defined(DEBUG) px_ksprintf(dbg_buf, "@ 0x%p [0x%lx]\n", chunk, size2); px_rs232_print(dbg_buf); - +#endif size_t len = 0; if (size + sizeof(px_heap_chunk_t) <= size2) { @@ -173,10 +180,10 @@ void* malloc(size_t size) { dlist_insert_after(&chunk->all, &chunk2->all); len = px_memory_chunk_size(chunk2); int n = px_memory_chunk_slot(len); - +#if defined(DEBUG) px_ksprintf(dbg_buf, " adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); px_rs232_print(dbg_buf); - +#endif DLIST_PUSH(&free_chunk[n], chunk2, free); mem_meta += HEADER_SIZE; mem_free += len - HEADER_SIZE; @@ -184,13 +191,16 @@ void* malloc(size_t size) { chunk->used = 1; memset(chunk->data, 0xAA, size); +#if defined(DEBUG) px_ksprintf(dbg_buf, "AAAA\n"); px_rs232_print(dbg_buf); - +#endif mem_free -= size2; mem_used += size2 - len - HEADER_SIZE; +#if defined(DEBUG) px_ksprintf(dbg_buf, " = %p [%p]\n", chunk->data, chunk); px_rs232_print(dbg_buf); +#endif return chunk->data; } @@ -198,7 +208,7 @@ void free(void* mem) { px_heap_chunk_t* chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); - +#if defined(DEBUG) px_ksprintf(dbg_buf, "%s(0x%p): 0x@%p 0x%lx [%d]\n", __FUNCTION__, mem, @@ -207,7 +217,7 @@ void free(void* mem) { px_memory_chunk_slot(px_memory_chunk_size(chunk)) ); px_rs232_print(dbg_buf); - +#endif mem_used -= px_memory_chunk_size(chunk); if (next->used == 0) { diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 61f0242d..27266316 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -101,18 +101,19 @@ static void px_paging_init_dir() { } static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { - char dbg[300]; // Set the page directory entry (pde) and page table entry (pte) uint32_t pde = vaddr.page_dir_index; uint32_t pte = vaddr.page_table_index; - px_page_table_entry *entry = &(page_tables[pde].pages[pte]); - // Print a debug message to serial - px_ksprintf(dbg, "map 0x%08x to 0x%08x, pde = 0x%08x, pte = 0x%08x\n", paddr, vaddr.val, pde, pte); - px_rs232_print(dbg); // If the page's virtual address is not aligned if (vaddr.page_offset != 0) { PANIC("Attempted to map a non-page-aligned virtual address.\n"); } +#if defined(DEBUG) + // Print a debug message to serial + char dbg[300]; + px_page_table_entry *entry = &(page_tables[pde].pages[pte]); + px_ksprintf(dbg, "map 0x%08x to 0x%08x, pde = 0x%08x, pte = 0x%08x\n", paddr, vaddr.val, pde, pte); + px_rs232_print(dbg); // If the page is already mapped into memory if (entry->present) { size_t bit_idx = INDEX_FROM_BIT(vaddr.val >> 12); @@ -129,6 +130,7 @@ static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { px_rs232_print(dbg); PANIC("Attempted to map already mapped page.\n"); } +#endif // Set the page information page_tables[pde].pages[pte] = { .present = 1, // The page is present @@ -142,8 +144,10 @@ static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { } static void px_paging_map_early_mem() { - px_virtual_address_t a; +#if defined(DEBUG) px_rs232_print("==== MAP EARLY MEM ====\n"); +#endif + px_virtual_address_t a; for (a = VADDR(0); a.val < 0x100000; a.val += PAGE_SIZE) { // identity map the early memory px_map_kernel_page(a, a.val); @@ -151,11 +155,13 @@ static void px_paging_map_early_mem() { } static void px_paging_map_hh_kernel() { - px_virtual_address_t addr; +#if defined(DEBUG) px_rs232_print("==== MAP HH KERNEL ====\n"); - for (addr = VADDR(KERNEL_START); addr.val < KERNEL_END; addr.val += PAGE_SIZE) { +#endif + px_virtual_address_t a; + for (a = VADDR(KERNEL_START); a.val < KERNEL_END; a.val += PAGE_SIZE) { // map the higher-half kernel in - px_map_kernel_page(addr, KADDR_TO_PHYS(addr.val)); + px_map_kernel_page(a, KADDR_TO_PHYS(a.val)); } } From 5c540ff88fdcf7a84af756542959157bd3e752a0 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 7 Oct 2020 20:20:54 -0400 Subject: [PATCH 036/139] Updated include path for VSCode --- .vscode/c_cpp_properties.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index fd0f9ca9..23218b5d 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -6,7 +6,7 @@ "compilerPath": "/usr/bin/gcc", "includePath": [ "${default}", - "${workspaceFolder}/sysroot/usr/include/kernel" + "${workspaceFolder}/sysroot/usr/include/kernel/**" ], "cStandard": "c11", "cppStandard": "c++17", From 62f0ee95851475f4c3d81ea54f09e8f81c6b5b83 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 7 Oct 2020 20:30:33 -0400 Subject: [PATCH 037/139] Created px_debugf to handle debug output --- kernel/lib/debug.cpp | 35 ++++++++++++++ kernel/mem/heap.cpp | 58 +++++------------------- kernel/mem/paging.cpp | 16 ++----- sysroot/usr/include/kernel/lib/stdio.hpp | 19 ++++++-- 4 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 kernel/lib/debug.cpp diff --git a/kernel/lib/debug.cpp b/kernel/lib/debug.cpp new file mode 100644 index 00000000..548114e3 --- /dev/null +++ b/kernel/lib/debug.cpp @@ -0,0 +1,35 @@ +/** + * @file debug.cpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @brief + * @version 0.1 + * @date 2020-10-07 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#include +#include +#include + +int px_debugf(const char* fmt, ...) { + // Return counter + int ret = 0; +#if defined(DEBUG) + // Create the arguments list + va_list args; + va_start(args, fmt); + // Statically allocate a print buffer + // since we may call this before we + // have paging available. + char buf[1024]; + // Write the string to the buffer + ret = px_kvsprintf(buf, fmt, args); + // Print to serial + px_rs232_print(buf); +#else + (void)fmt; +#endif + return ret; +} diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index da3b9586..b203f533 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -35,25 +35,16 @@ px_heap_chunk_t* first = NULL; px_heap_chunk_t* last = NULL; void* slot[NUM_SLOTS] = { NULL }; -#if defined(DEBUG) -char dbg_buf[64] = {0}; -#endif static void px_memory_chunk_init(px_heap_chunk_t* chunk) { -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); - px_rs232_print(dbg_buf); -#endif + px_debugf("%s(0x%p)\n", __FUNCTION__, chunk); dlist_init(&chunk->all); chunk->used = 0; dlist_init(&chunk->free); } static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%p)\n", __FUNCTION__, chunk); - px_rs232_print(dbg_buf); -#endif + px_debugf("%s(0x%p)\n", __FUNCTION__, chunk); char* end = (char*)(chunk->all.next); char* start = (char*)(&chunk->all); return (end - start) - HEADER_SIZE; @@ -71,10 +62,7 @@ static int px_memory_chunk_slot(size_t size) { static void px_remove_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%p) : removing chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); - px_rs232_print(dbg_buf); -#endif + px_debugf("%s(0x%p) : removing chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); mem_free -= len - HEADER_SIZE; } @@ -82,10 +70,7 @@ static void px_remove_free(px_heap_chunk_t* chunk) { static void px_push_free(px_heap_chunk_t* chunk) { size_t len = px_memory_chunk_size(chunk); int n = px_memory_chunk_slot(len); -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%p) : adding chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); - px_rs232_print(dbg_buf); -#endif + px_debugf("%s(0x%p) : adding chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); DLIST_PUSH(&free_chunk[n], chunk, free); mem_free += len - HEADER_SIZE; } @@ -134,10 +119,7 @@ void px_heap_init(size_t size) { // Get the sizes and number of chunks size_t len = px_memory_chunk_size(second); int n = px_memory_chunk_slot(len); -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%p, 0x%lx) : adding chunk 0x%lx [%d]\n", __FUNCTION__, mem, size, len, n); - px_rs232_print(dbg_buf); -#endif + px_debugf("%s(0x%p, 0x%lx) : adding chunk 0x%lx [%d]\n", __FUNCTION__, mem, size, len, n); // Push them onto the linked list and update tracking variables DLIST_PUSH(&free_chunk[n], second, free); mem_free = len - HEADER_SIZE; @@ -145,10 +127,7 @@ void px_heap_init(size_t size) { } void* malloc(size_t size) { -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%lx)\n", __FUNCTION__, size); - px_rs232_print(dbg_buf); -#endif + px_debugf("%s(0x%lx)\n", __FUNCTION__, size); size = (size + ALIGN - 1) & (~(ALIGN - 1)); if (size < MIN_SIZE) { @@ -168,10 +147,7 @@ void* malloc(size_t size) { px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); size_t size2 = px_memory_chunk_size(chunk); -#if defined(DEBUG) - px_ksprintf(dbg_buf, "@ 0x%p [0x%lx]\n", chunk, size2); - px_rs232_print(dbg_buf); -#endif + px_debugf("@ 0x%p [0x%lx]\n", chunk, size2); size_t len = 0; if (size + sizeof(px_heap_chunk_t) <= size2) { @@ -180,10 +156,7 @@ void* malloc(size_t size) { dlist_insert_after(&chunk->all, &chunk2->all); len = px_memory_chunk_size(chunk2); int n = px_memory_chunk_slot(len); -#if defined(DEBUG) - px_ksprintf(dbg_buf, " adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); - px_rs232_print(dbg_buf); -#endif + px_debugf(" adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); DLIST_PUSH(&free_chunk[n], chunk2, free); mem_meta += HEADER_SIZE; mem_free += len - HEADER_SIZE; @@ -191,16 +164,10 @@ void* malloc(size_t size) { chunk->used = 1; memset(chunk->data, 0xAA, size); -#if defined(DEBUG) - px_ksprintf(dbg_buf, "AAAA\n"); - px_rs232_print(dbg_buf); -#endif + px_debugf("AAAA\n"); mem_free -= size2; mem_used += size2 - len - HEADER_SIZE; -#if defined(DEBUG) - px_ksprintf(dbg_buf, " = %p [%p]\n", chunk->data, chunk); - px_rs232_print(dbg_buf); -#endif + px_debugf(" = %p [%p]\n", chunk->data, chunk); return chunk->data; } @@ -208,16 +175,13 @@ void free(void* mem) { px_heap_chunk_t* chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); -#if defined(DEBUG) - px_ksprintf(dbg_buf, "%s(0x%p): 0x@%p 0x%lx [%d]\n", + px_debugf("%s(0x%p): 0x@%p 0x%lx [%d]\n", __FUNCTION__, mem, chunk, px_memory_chunk_size(chunk), px_memory_chunk_slot(px_memory_chunk_size(chunk)) ); - px_rs232_print(dbg_buf); -#endif mem_used -= px_memory_chunk_size(chunk); if (next->used == 0) { diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 27266316..626524d4 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -110,15 +110,12 @@ static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { } #if defined(DEBUG) // Print a debug message to serial - char dbg[300]; px_page_table_entry *entry = &(page_tables[pde].pages[pte]); - px_ksprintf(dbg, "map 0x%08x to 0x%08x, pde = 0x%08x, pte = 0x%08x\n", paddr, vaddr.val, pde, pte); - px_rs232_print(dbg); + px_debugf("map 0x%08x to 0x%08x, pde = 0x%08x, pte = 0x%08x\n", paddr, vaddr.val, pde, pte); // If the page is already mapped into memory if (entry->present) { size_t bit_idx = INDEX_FROM_BIT(vaddr.val >> 12); - px_ksprintf( - dbg, + px_debugf( "pte { present = %d, read_write = %d, usermode = %d, " "write_through = %d,\n cache_disable = %d, accessed = %d, " "dirty = %d,\n page_att_table = %d, global = %d, frame = 0x%08x\n}\n" @@ -127,7 +124,6 @@ static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { entry->cache_disable, entry->accessed, entry->dirty, entry->page_att_table, entry->global, entry->frame, mapped_pages[bit_idx - 1], mapped_pages[bit_idx], mapped_pages[bit_idx + 1]); - px_rs232_print(dbg); PANIC("Attempted to map already mapped page.\n"); } #endif @@ -144,9 +140,7 @@ static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { } static void px_paging_map_early_mem() { -#if defined(DEBUG) - px_rs232_print("==== MAP EARLY MEM ====\n"); -#endif + px_debugf("==== MAP EARLY MEM ====\n"); px_virtual_address_t a; for (a = VADDR(0); a.val < 0x100000; a.val += PAGE_SIZE) { // identity map the early memory @@ -155,9 +149,7 @@ static void px_paging_map_early_mem() { } static void px_paging_map_hh_kernel() { -#if defined(DEBUG) - px_rs232_print("==== MAP HH KERNEL ====\n"); -#endif + px_debugf("==== MAP HH KERNEL ====\n"); px_virtual_address_t a; for (a = VADDR(KERNEL_START); a.val < KERNEL_END; a.val += PAGE_SIZE) { // map the higher-half kernel in diff --git a/sysroot/usr/include/kernel/lib/stdio.hpp b/sysroot/usr/include/kernel/lib/stdio.hpp index 444d1680..94507df0 100644 --- a/sysroot/usr/include/kernel/lib/stdio.hpp +++ b/sysroot/usr/include/kernel/lib/stdio.hpp @@ -22,7 +22,7 @@ * @param buf Pointer to a buffer where the result is stored * @param fmt C string that contains a format string * @param args A value identifying a variable arguments list - * @return int The total number of character written. + * @return int The total number of characters written. * The number of characters not written if negative. */ int px_kvsprintf(char* buf, const char* fmt, va_list args); @@ -32,7 +32,7 @@ int px_kvsprintf(char* buf, const char* fmt, va_list args); * @param buf Pointer to a buffer where the result is stored * @param fmt C string that contains a format string * @param ... Sequence of additional arguments - * @return int The total number of character written. + * @return int The total number of characters written. * The number of characters not written if negative. */ int px_ksprintf(char* buf, const char* fmt, ...); @@ -41,7 +41,7 @@ int px_ksprintf(char* buf, const char* fmt, ...); * * @param fmt C string that contains a format string * @param args A value identifying a variable arguments list - * @return int The total number of character written. + * @return int The total number of characters written. * The number of characters not written if negative. */ int px_kvprintf(const char* fmt, va_list args); @@ -50,7 +50,7 @@ int px_kvprintf(const char* fmt, va_list args); * * @param fmt C string that contains a format string * @param ... Sequence of additional arguments - * @return int The total number of character written. + * @return int The total number of characters written. * The number of characters not written if negative. */ int px_kprintf(const char* fmt, ...); @@ -65,4 +65,13 @@ int putchar(char c); * * @param str String to be printed. */ -int puts(const char *str); \ No newline at end of file +int puts(const char *str); +/** + * @brief Prints a statement to serial debugger if the kernel + * is built with the debug flag defined. Max message size is + * 1024 (including null terminator). + * @param fmt Formatted C string + * @param ... Sequence of additional arguments + * @return int The total number of characters written. + */ +int px_debugf(const char* fmt, ...); \ No newline at end of file From 5b0d93c22d1ad942f3b455b4a814b3930c570375 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 7 Oct 2020 20:43:19 -0400 Subject: [PATCH 038/139] Fixed most whitespace issues --- kernel/arch/arch.cpp | 10 +- kernel/arch/i386/boot.s | 130 +++++++++--------- kernel/arch/i386/gdt.cpp | 32 ++--- kernel/lib/linked_list.cpp | 24 ++-- kernel/lib/printf.cpp | 50 +++---- kernel/main.cpp | 2 +- sysroot/usr/include/kernel/arch/i386/tss.hpp | 54 ++++---- .../usr/include/kernel/lib/linked_list.hpp | 80 +++++------ sysroot/usr/include/kernel/mem/heap.hpp | 4 +- 9 files changed, 193 insertions(+), 193 deletions(-) diff --git a/kernel/arch/arch.cpp b/kernel/arch/arch.cpp index 8a96b15c..55cee2ba 100644 --- a/kernel/arch/arch.cpp +++ b/kernel/arch/arch.cpp @@ -47,9 +47,9 @@ static inline int px_arch_cpuid_vendor(int flag, int regs[4]) { } const char* const px_cpu_get_vendor() { - static char vendor[16]; - px_arch_cpuid_vendor(0, (int *)(vendor)); - return vendor; + static char vendor[16]; + px_arch_cpuid_vendor(0, (int *)(vendor)); + return vendor; } const char* const px_cpu_get_model() { @@ -57,10 +57,10 @@ const char* const px_cpu_get_model() { // EAX, EBX, ECX, and EDX to store the string, so we basically // are appending all 4 register values to this char array each time. static char model[48]; - px_arch_cpuid(0x80000002, (int *)(model)); + px_arch_cpuid(0x80000002, (int *)(model)); px_arch_cpuid(0x80000003, (int *)(model+16)); px_arch_cpuid(0x80000004, (int *)(model+32)); - return model; + return model; } /** diff --git a/kernel/arch/i386/boot.s b/kernel/arch/i386/boot.s index 493e27e6..5e5d45c1 100644 --- a/kernel/arch/i386/boot.s +++ b/kernel/arch/i386/boot.s @@ -41,21 +41,21 @@ .section .early_text, "ax", @progbits _start: # save our multiboot information from grub before messing with registers - # these can't be saved on the stack as we are about to zero it - movl %eax, multiboot_magic - movl %ebx, multiboot_info - - # zero the early BSS to start things off well - movl $_EARLY_BSS_SIZE, %ecx - xorb %al, %al - movl $_EARLY_BSS_START, %edi - rep - stosb - - # identity map from 0x00000000 -> LOWMEM_END - # WARNING: code assumes that the kernel won't be greater than 3MB - movl $lowmem_pt, %eax - movl %eax, page_directory + # these can't be saved on the stack as we are about to zero it + movl %eax, multiboot_magic + movl %ebx, multiboot_info + + # zero the early BSS to start things off well + movl $_EARLY_BSS_SIZE, %ecx + xorb %al, %al + movl $_EARLY_BSS_START, %edi + rep + stosb + + # identity map from 0x00000000 -> LOWMEM_END + # WARNING: code assumes that the kernel won't be greater than 3MB + movl $lowmem_pt, %eax + movl %eax, page_directory orl $PAGE_PERM, page_directory xor %eax, %eax @@ -70,14 +70,14 @@ _start: cmpl $LOWMEM_END, %eax jl _start.lowmem - # create virtual mappings for the kernel in the higher-half - movl $_KERNEL_START, %edx - shrl $22, %edx # find which directory entry we need to use + # create virtual mappings for the kernel in the higher-half + movl $_KERNEL_START, %edx + shrl $22, %edx # find which directory entry we need to use # the first page table - movl $kernel_pt, %eax - movl %eax, page_directory(,%edx,4) - orl $PAGE_PERM, page_directory(,%edx,4) + movl $kernel_pt, %eax + movl %eax, page_directory(,%edx,4) + orl $PAGE_PERM, page_directory(,%edx,4) # the second page table incl %edx @@ -85,79 +85,79 @@ _start: movl %eax, page_directory(,%edx,4) orl $PAGE_PERM, page_directory(,%edx,4) - movl $_KERNEL_START, %eax # the kernel's current virtual start - _start.higher: + movl $_KERNEL_START, %eax # the kernel's current virtual start + _start.higher: # compute the page table offset # this only works because the two page tables are adjacent - movl %eax, %edx + movl %eax, %edx shrl $22, %edx subl $0x300, %edx imull $PAGE_SIZE, %edx movl %eax, %ecx - shrl $PAGE_SHIFT, %ecx - andl $0x3ff, %ecx # generate kernel PTE index - - movl %eax, %ebx - subl $KERNEL_BASE, %ebx # convert virt->physical - movl %ebx, kernel_pt(%edx,%ecx,4) - orl $PAGE_PERM, kernel_pt(%edx,%ecx,4) - - addl $PAGE_SIZE, %eax # move on to the next page - cmpl $_KERNEL_END, %eax # are we done mapping in the kernel? - jl _start.higher - - movl $page_directory, %eax - movl %eax, %cr3 # load CR3 with our page directory - - movl %cr0, %eax - orl $0x80000000, %eax - movl %eax, %cr0 # enable paging! make sure the next instruction fetch doesnt page fault - - # zero the kernel BSS - movl $_BSS_SIZE, %ecx - xorb %al, %al - movl $_BSS_START, %edi - rep - stosb - - # adjust the stack in to the virtual area - # setup and adjust the stack - movl $(stack + STACK_SIZE), %esp - - pushl multiboot_magic # Multiboot magic number - pushl multiboot_info # Multiboot info structure + shrl $PAGE_SHIFT, %ecx + andl $0x3ff, %ecx # generate kernel PTE index + + movl %eax, %ebx + subl $KERNEL_BASE, %ebx # convert virt->physical + movl %ebx, kernel_pt(%edx,%ecx,4) + orl $PAGE_PERM, kernel_pt(%edx,%ecx,4) + + addl $PAGE_SIZE, %eax # move on to the next page + cmpl $_KERNEL_END, %eax # are we done mapping in the kernel? + jl _start.higher + + movl $page_directory, %eax + movl %eax, %cr3 # load CR3 with our page directory + + movl %cr0, %eax + orl $0x80000000, %eax + movl %eax, %cr0 # enable paging! make sure the next instruction fetch doesnt page fault + + # zero the kernel BSS + movl $_BSS_SIZE, %ecx + xorb %al, %al + movl $_BSS_START, %edi + rep + stosb + + # adjust the stack in to the virtual area + # setup and adjust the stack + movl $(stack + STACK_SIZE), %esp + + pushl multiboot_magic # Multiboot magic number + pushl multiboot_info # Multiboot info structure # Set NULL stack frame for trace xor %ebp, %ebp - # Enter the high-level kernel. + # Enter the high-level kernel. call px_kernel_main # By this point we should be into the wild world of C++ # So, this should never be called unless the kernel returns _start.catchfire: - hlt - jmp _start.catchfire + hlt + jmp _start.catchfire .section .early_bss, "aw", @nobits .align 4096 page_directory: # should also be page aligned (hopefully) - .space 1024*4 # reserve 1024 DWORDs for our page table pointers + .space 1024*4 # reserve 1024 DWORDs for our page table pointers lowmem_pt: - .space 1024*4 # lowmem identity mappings + .space 1024*4 # lowmem identity mappings kernel_pt: - .space 1024*4 # our kernel page table mappings + .space 1024*4 # our kernel page table mappings pages_pt: .space 1024*4 # a page table that maps pages that contain page tables .section .early_data, "aw", @nobits multiboot_magic: - .long 0 + .long 0 multiboot_info: - .long 0 + .long 0 .section .bss, "aw", @nobits .align 4 stack: - .space STACK_SIZE + .space STACK_SIZE /* vim: ft=gas : */ diff --git a/kernel/arch/i386/gdt.cpp b/kernel/arch/i386/gdt.cpp index a7d64a8c..9889ef6d 100644 --- a/kernel/arch/i386/gdt.cpp +++ b/kernel/arch/i386/gdt.cpp @@ -32,26 +32,26 @@ void px_gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint16_t flags) // the physical limit or get overlap with other segments) so we have to // compensate this by decreasing a higher bit (and might have up to // 4095 wasted bytes behind the used memory) - uint64_t descriptor = 0; + uint64_t descriptor = 0; - // Create the high 32 bit segment - descriptor = base & 0xFF000000; // base direct map - descriptor |= (base >> 16) & 0x000000FF; // base 23-16 : 7-0 - descriptor |= (flags << 8) & 0x00F0FF00; // flags 16-11 : 24-19 7-0 : 15-8 - descriptor |= limit & 0x000F0000; // limit direct map - // Shift by 32 to move to the lower half of the section - descriptor <<= 32; - // Create the low 32 bit segment - descriptor |= (base << 16) & 0xFFFF0000; // base 15-0 : 31-16 - descriptor |= limit & 0x0000FFFF; // limit direct map - // Copy the descriptor value into our GDT entries array - memcpy(&gdt_entries[num], &descriptor, sizeof(uint64_t)); + // Create the high 32 bit segment + descriptor = base & 0xFF000000; // base direct map + descriptor |= (base >> 16) & 0x000000FF; // base 23-16 : 7-0 + descriptor |= (flags << 8) & 0x00F0FF00; // flags 16-11 : 24-19 7-0 : 15-8 + descriptor |= limit & 0x000F0000; // limit direct map + // Shift by 32 to move to the lower half of the section + descriptor <<= 32; + // Create the low 32 bit segment + descriptor |= (base << 16) & 0xFFFF0000; // base 15-0 : 31-16 + descriptor |= limit & 0x0000FFFF; // limit direct map + // Copy the descriptor value into our GDT entries array + memcpy(&gdt_entries[num], &descriptor, sizeof(uint64_t)); } //gdt_flush((uintptr_t)gdtp); void px_gdt_install() { - px_kprintf(DBG_INFO "Installing the GDT...\n"); - gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1; + px_kprintf(DBG_INFO "Installing the GDT...\n"); + gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1; gdt_ptr.base = (uint32_t)&gdt_entries; px_gdt_set_gate(0, 0, 0, 0); // Null segment @@ -61,5 +61,5 @@ void px_gdt_install() { px_gdt_set_gate(4, 0, 0x000FFFFF, GDT_DATA_PL3); // User mode data segment gdt_flush((uint32_t)&gdt_ptr); - px_kprintf(DBG_OKAY "Installed the GDT.\n"); + px_kprintf(DBG_OKAY "Installed the GDT.\n"); } \ No newline at end of file diff --git a/kernel/lib/linked_list.cpp b/kernel/lib/linked_list.cpp index 2d7214e9..03b4d31c 100644 --- a/kernel/lib/linked_list.cpp +++ b/kernel/lib/linked_list.cpp @@ -16,14 +16,14 @@ // initialize a one element DList void dlist_init(DList *dlist) { - //px_kprintf("%s(%p)\n", __FUNCTION__, dlist); + //px_kprintf("%s(%p)\n", __FUNCTION__, dlist); dlist->next = dlist; dlist->prev = dlist; } // insert d2 after d1 void dlist_insert_after(DList *d1, DList *d2) { - //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1, d2); DList *n1 = d1->next; DList *e2 = d2->prev; @@ -35,7 +35,7 @@ void dlist_insert_after(DList *d1, DList *d2) { // insert d2 before d1 void dlist_insert_before(DList *d1, DList *d2) { - //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1, d2); DList *e1 = d1->prev; DList *e2 = d2->prev; @@ -47,7 +47,7 @@ void dlist_insert_before(DList *d1, DList *d2) { // remove d from the list void dlist_remove(DList *d) { - //px_kprintf("%s(%p)\n", __FUNCTION__, d); + //px_kprintf("%s(%p)\n", __FUNCTION__, d); d->prev->next = d->next; d->next->prev = d->prev; d->next = d; @@ -56,33 +56,33 @@ void dlist_remove(DList *d) { // push d2 to the front of the d1p list void dlist_push(DList **d1p, DList *d2) { - //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); if (*d1p != NULL) { - dlist_insert_before(*d1p, d2); + dlist_insert_before(*d1p, d2); } *d1p = d2; } // pop the front of the dp list DList* dlist_pop(DList **dp) { - //px_kprintf("%s(%p)\n", __FUNCTION__, dp); + //px_kprintf("%s(%p)\n", __FUNCTION__, dp); DList *d1 = *dp; DList *d2 = d1->next; dlist_remove(d1); if (d1 == d2) { - *dp = NULL; + *dp = NULL; } else { - *dp = d2; + *dp = d2; } return d1; } // remove d2 from the list, advancing d1p if needed void dlist_remove_from(DList **d1p, DList *d2) { - //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); + //px_kprintf("%s(%p, %p)\n", __FUNCTION__, d1p, d2); if (*d1p == d2) { - dlist_pop(d1p); + dlist_pop(d1p); } else { - dlist_remove(d2); + dlist_remove(d2); } } \ No newline at end of file diff --git a/kernel/lib/printf.cpp b/kernel/lib/printf.cpp index a17da3ef..6ce11313 100644 --- a/kernel/lib/printf.cpp +++ b/kernel/lib/printf.cpp @@ -21,7 +21,7 @@ /***************************************************************************** Stripped-down printf() -Chris Giese http://www.execpc.com/~geezer +Chris Giese http://www.execpc.com/~geezer Release date: Dec 12, 2003 This code is public domain (no copyright). You can do whatever you want with it. @@ -41,31 +41,31 @@ Revised May 12, 2000 - actually did some TESTING, maybe fixed some other bugs %[flag][width][.prec][mod][conv] -flag: - - left justify, pad right w/ blanks DONE - 0 pad left w/ 0 for numerics DONE - + always print sign, + or - no - ' ' (blank) no - # (???) no +flag: + - left justify, pad right w/ blanks DONE + 0 pad left w/ 0 for numerics DONE + + always print sign, + or - no + ' ' (blank) no + # (???) no -width: (field width) DONE +width: (field width) DONE -prec: (precision) no +prec: (precision) no -conv: d,i decimal int DONE - u decimal unsigned DONE - o octal DONE - x,X hex DONE - f,e,g,E,G float no - c char DONE - s string DONE - p ptr DONE +conv: d,i decimal int DONE + u decimal unsigned DONE + o octal DONE + x,X hex DONE + f,e,g,E,G float no + c char DONE + s string DONE + p ptr DONE -mod: N near ptr DONE - F far ptr no - h short (16-bit) int DONE - l long (32-bit) int DONE - L long long (64-bit) int no +mod: N near ptr DONE + F far ptr no + h short (16-bit) int DONE + l long (32-bit) int DONE + L long long (64-bit) int no *****************************************************************************/ /* Assume: width of stack == width of int. Don't use sizeof(char *) or @@ -93,9 +93,9 @@ Using & for division here, so STACK_WIDTH must be a power of 2. */ typedef int (*fnptr_t)(unsigned c, void** helper); /***************************************************************************** -name: do_printf -action: minimal subfunction for ?printf, calls function - 'fn' with arg 'ptr' for each character to be output +name: do_printf +action: minimal subfunction for ?printf, calls function + 'fn' with arg 'ptr' for each character to be output returns:total number of characters output *****************************************************************************/ int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr) diff --git a/kernel/main.cpp b/kernel/main.cpp index 87b1c5f7..a5400a4d 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -76,7 +76,7 @@ extern "C" void px_call_constructors() { uintptr_t __stack_chk_guard = STACK_CHK_GUARD; extern "C" void __stack_chk_fail(void) { - PANIC("Smashed stack detected."); + PANIC("Smashed stack detected."); } /** diff --git a/sysroot/usr/include/kernel/arch/i386/tss.hpp b/sysroot/usr/include/kernel/arch/i386/tss.hpp index fca71636..1c32d62e 100644 --- a/sysroot/usr/include/kernel/arch/i386/tss.hpp +++ b/sysroot/usr/include/kernel/arch/i386/tss.hpp @@ -36,33 +36,33 @@ extern "C" void tss_flush(); * */ typedef struct tss_entry { - uint32_t prev; // The previous TSS - if we used hardware task switching this would form a linked list. - uint32_t esp0; // The stack pointer to load when we change to kernel mode. - uint32_t ss0; // The stack segment to load when we change to kernel mode. - uint32_t esp1; // everything below here is unusued now but required by Intel... - uint32_t ss1; - uint32_t esp2; - uint32_t ss2; - uint32_t cr3; - uint32_t eip; - uint32_t eflags; - uint32_t eax; - uint32_t ecx; - uint32_t edx; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint32_t es; - uint32_t cs; - uint32_t ss; - uint32_t ds; - uint32_t fs; - uint32_t gs; - uint32_t ldt; - uint16_t trap; - uint16_t iomap_base; + uint32_t prev; // The previous TSS - if we used hardware task switching this would form a linked list. + uint32_t esp0; // The stack pointer to load when we change to kernel mode. + uint32_t ss0; // The stack segment to load when we change to kernel mode. + uint32_t esp1; // everything below here is unusued now but required by Intel... + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; } __attribute__ ((packed)) tss_entry_t; #endif /* PANIX_TASK_STATE_SEGMENT */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/lib/linked_list.hpp b/sysroot/usr/include/kernel/lib/linked_list.hpp index 01a24c50..e7c9500d 100644 --- a/sysroot/usr/include/kernel/lib/linked_list.hpp +++ b/sysroot/usr/include/kernel/lib/linked_list.hpp @@ -16,54 +16,54 @@ #include #include -#define DLIST_REMOVE_FROM(h, d, l) \ - { \ +#define DLIST_REMOVE_FROM(h, d, l) \ + { \ __typeof__(**h) **h_ = h, *d_ = d; \ - DList *head = &(*h_)->l; \ - dlist_remove_from(&head, &d_->l); \ - if (head == NULL) { \ - *h_ = NULL; \ - } else { \ - *h_ = CONTAINER(__typeof__(**h), l, head); \ - } \ + DList *head = &(*h_)->l; \ + dlist_remove_from(&head, &d_->l); \ + if (head == NULL) { \ + *h_ = NULL; \ + } else { \ + *h_ = CONTAINER(__typeof__(**h), l, head); \ + } \ } -#define DLIST_PUSH(h, v, l) \ - { \ - __typeof__(*v) **h_ = h, *v_ = v; \ - DList *head = &(*h_)->l; \ - if (*h_ == NULL) head = NULL; \ - dlist_push(&head, &v_->l); \ - *h_ = CONTAINER(__typeof__(*v), l, head); \ +#define DLIST_PUSH(h, v, l) \ + { \ + __typeof__(*v) **h_ = h, *v_ = v; \ + DList *head = &(*h_)->l; \ + if (*h_ == NULL) head = NULL; \ + dlist_push(&head, &v_->l); \ + *h_ = CONTAINER(__typeof__(*v), l, head); \ } -#define DLIST_POP(h, l) \ - ({ \ - __typeof__(**h) **h_ = h; \ - DList *head = &(*h_)->l; \ - DList *res = dlist_pop(&head); \ - if (head == NULL) { \ - *h_ = NULL; \ - } else { \ - *h_ = CONTAINER(__typeof__(**h), l, head); \ - } \ - CONTAINER(__typeof__(**h), l, res); \ +#define DLIST_POP(h, l) \ + ({ \ + __typeof__(**h) **h_ = h; \ + DList *head = &(*h_)->l; \ + DList *res = dlist_pop(&head); \ + if (head == NULL) { \ + *h_ = NULL; \ + } else { \ + *h_ = CONTAINER(__typeof__(**h), l, head); \ + } \ + CONTAINER(__typeof__(**h), l, res); \ }) -#define DLIST_ITERATOR_BEGIN(h, l, it) \ - { \ - __typeof__(*h) *h_ = h; \ - DList *last_##it = h_->l.prev, *iter_##it = &h_->l, *next_##it; \ - do { \ - if (iter_##it == last_##it) { \ - next_##it = NULL; \ - } else { \ - next_##it = iter_##it->next; \ - } \ - __typeof__(*h)* it = CONTAINER(__typeof__(*h), l, iter_##it); +#define DLIST_ITERATOR_BEGIN(h, l, it) \ + { \ + __typeof__(*h) *h_ = h; \ + DList *last_##it = h_->l.prev, *iter_##it = &h_->l, *next_##it; \ + do { \ + if (iter_##it == last_##it) { \ + next_##it = NULL; \ + } else { \ + next_##it = iter_##it->next; \ + } \ + __typeof__(*h)* it = CONTAINER(__typeof__(*h), l, iter_##it); -#define DLIST_ITERATOR_END(it) \ - } while((iter_##it = next_##it)); \ +#define DLIST_ITERATOR_END(it) \ + } while((iter_##it = next_##it)); \ } #define DLIST_ITERATOR_REMOVE_FROM(h, it, l) DLIST_REMOVE_FROM(h, iter_##it, l) diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 85554829..260733c8 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -23,8 +23,8 @@ typedef struct px_heap_chunk { DList all; int used; union { - char data[0]; - DList free; + char data[0]; + DList free; }; } px_heap_chunk_t; From 367e978c3510cca1b2cb11eee5381f2c3d18b612 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 7 Oct 2020 20:44:53 -0400 Subject: [PATCH 039/139] Fixed remaining stubborn whitespace issues --- kernel/lib/string.cpp | 56 +++++++++++------------ kernel/mem/heap.cpp | 104 +++++++++++++++++++++--------------------- 2 files changed, 80 insertions(+), 80 deletions(-) diff --git a/kernel/lib/string.cpp b/kernel/lib/string.cpp index 748b64e7..9dff0d10 100644 --- a/kernel/lib/string.cpp +++ b/kernel/lib/string.cpp @@ -65,41 +65,41 @@ void itoa(int n, char str[]) { } void* memset(void* bufptr, int value, size_t size) { - unsigned char* buf = (unsigned char*) bufptr; - for (size_t i = 0; i < size; i++) - buf[i] = (unsigned char) value; - return bufptr; + unsigned char* buf = (unsigned char*) bufptr; + for (size_t i = 0; i < size; i++) + buf[i] = (unsigned char) value; + return bufptr; } int memcmp(const void* ptr1, const void* ptr2, size_t size) { - const unsigned char* a = (const unsigned char*) ptr1; - const unsigned char* b = (const unsigned char*) ptr2; - for (size_t i = 0; i < size; i++) { - if (a[i] < b[i]) - return -1; - else if (a[i] > b[i]) - return 1; - } - return 0; + const unsigned char* a = (const unsigned char*) ptr1; + const unsigned char* b = (const unsigned char*) ptr2; + for (size_t i = 0; i < size; i++) { + if (a[i] < b[i]) + return -1; + else if (a[i] > b[i]) + return 1; + } + return 0; } void* memmove(void* destination, const void* source, size_t size) { - unsigned char* dst = (unsigned char*) destination; - const unsigned char* src = (const unsigned char*) source; - if (dst < src) { - for (size_t i = 0; i < size; i++) - dst[i] = src[i]; - } else { - for (size_t i = size; i != 0; i--) - dst[i-1] = src[i-1]; - } - return destination; + unsigned char* dst = (unsigned char*) destination; + const unsigned char* src = (const unsigned char*) source; + if (dst < src) { + for (size_t i = 0; i < size; i++) + dst[i] = src[i]; + } else { + for (size_t i = size; i != 0; i--) + dst[i-1] = src[i-1]; + } + return destination; } void* memcpy(void* dstptr, const void* srcptr, size_t size) { - unsigned char* dst = (unsigned char*) dstptr; - const unsigned char* src = (const unsigned char*) srcptr; - for (size_t i = 0; i < size; i++) - dst[i] = src[i]; - return dstptr; + unsigned char* dst = (unsigned char*) dstptr; + const unsigned char* src = (const unsigned char*) srcptr; + for (size_t i = 0; i < size; i++) + dst[i] = src[i]; + return dstptr; } \ No newline at end of file diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index b203f533..fd1f7b9c 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -53,8 +53,8 @@ static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { static int px_memory_chunk_slot(size_t size) { int n = -1; while(size > 0) { - ++n; - size /= 2; + ++n; + size /= 2; } return n; } @@ -76,22 +76,22 @@ static void px_push_free(px_heap_chunk_t* chunk) { } void check(void) { - int i; + int i; px_heap_chunk_t* t = last; - DLIST_ITERATOR_BEGIN(first, all, it) { - assert(CONTAINER(px_heap_chunk_t, all, it->all.prev) == t); - t = it; + DLIST_ITERATOR_BEGIN(first, all, it) { + assert(CONTAINER(px_heap_chunk_t, all, it->all.prev) == t); + t = it; } DLIST_ITERATOR_END(it); - for(i = 0; i < NUM_SIZES; ++i) { - if (free_chunk[i]) { - t = CONTAINER(px_heap_chunk_t, free, free_chunk[i]->free.prev); - DLIST_ITERATOR_BEGIN(free_chunk[i], free, it) { - assert(CONTAINER(px_heap_chunk_t, free, it->free.prev) == t); - t = it; - } DLIST_ITERATOR_END(it); - } + for (i = 0; i < NUM_SIZES; ++i) { + if (free_chunk[i]) { + t = CONTAINER(px_heap_chunk_t, free, free_chunk[i]->free.prev); + DLIST_ITERATOR_BEGIN(free_chunk[i], free, it) { + assert(CONTAINER(px_heap_chunk_t, free, it->free.prev) == t); + t = it; + } DLIST_ITERATOR_END(it); + } } } @@ -130,41 +130,41 @@ void* malloc(size_t size) { px_debugf("%s(0x%lx)\n", __FUNCTION__, size); size = (size + ALIGN - 1) & (~(ALIGN - 1)); - if (size < MIN_SIZE) { + if (size < MIN_SIZE) { size = MIN_SIZE; } - int n = px_memory_chunk_slot(size - 1) + 1; + int n = px_memory_chunk_slot(size - 1) + 1; - if (n >= NUM_SIZES) { + if (n >= NUM_SIZES) { return NULL; } - while(!free_chunk[n]) { - ++n; - if (n >= NUM_SIZES) return NULL; + while(!free_chunk[n]) { + ++n; + if (n >= NUM_SIZES) return NULL; } - px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); + px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); size_t size2 = px_memory_chunk_size(chunk); - px_debugf("@ 0x%p [0x%lx]\n", chunk, size2); + px_debugf("@ 0x%p [0x%lx]\n", chunk, size2); size_t len = 0; - if (size + sizeof(px_heap_chunk_t) <= size2) { - px_heap_chunk_t* chunk2 = (px_heap_chunk_t*)(((char*)chunk) + HEADER_SIZE + size); - px_memory_chunk_init(chunk2); - dlist_insert_after(&chunk->all, &chunk2->all); - len = px_memory_chunk_size(chunk2); - int n = px_memory_chunk_slot(len); - px_debugf(" adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); - DLIST_PUSH(&free_chunk[n], chunk2, free); - mem_meta += HEADER_SIZE; - mem_free += len - HEADER_SIZE; + if (size + sizeof(px_heap_chunk_t) <= size2) { + px_heap_chunk_t* chunk2 = (px_heap_chunk_t*)(((char*)chunk) + HEADER_SIZE + size); + px_memory_chunk_init(chunk2); + dlist_insert_after(&chunk->all, &chunk2->all); + len = px_memory_chunk_size(chunk2); + int n = px_memory_chunk_slot(len); + px_debugf(" adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); + DLIST_PUSH(&free_chunk[n], chunk2, free); + mem_meta += HEADER_SIZE; + mem_free += len - HEADER_SIZE; } - chunk->used = 1; + chunk->used = 1; memset(chunk->data, 0xAA, size); - px_debugf("AAAA\n"); + px_debugf("AAAA\n"); mem_free -= size2; mem_used += size2 - len - HEADER_SIZE; px_debugf(" = %p [%p]\n", chunk->data, chunk); @@ -175,7 +175,7 @@ void free(void* mem) { px_heap_chunk_t* chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); - px_debugf("%s(0x%p): 0x@%p 0x%lx [%d]\n", + px_debugf("%s(0x%p): 0x@%p 0x%lx [%d]\n", __FUNCTION__, mem, chunk, @@ -185,25 +185,25 @@ void free(void* mem) { mem_used -= px_memory_chunk_size(chunk); if (next->used == 0) { - // merge in next - px_remove_free(next); - dlist_remove(&next->all); - memset(next, 0xDD, sizeof(px_heap_chunk_t)); - mem_meta -= HEADER_SIZE; - mem_free += HEADER_SIZE; + // merge in next + px_remove_free(next); + dlist_remove(&next->all); + memset(next, 0xDD, sizeof(px_heap_chunk_t)); + mem_meta -= HEADER_SIZE; + mem_free += HEADER_SIZE; } if (prev->used == 0) { - // merge to prev - px_remove_free(prev); - dlist_remove(&chunk->all); - memset(chunk, 0xDD, sizeof(px_heap_chunk_t)); - px_push_free(prev); - mem_meta -= HEADER_SIZE; - mem_free += HEADER_SIZE; + // merge to prev + px_remove_free(prev); + dlist_remove(&chunk->all); + memset(chunk, 0xDD, sizeof(px_heap_chunk_t)); + px_push_free(prev); + mem_meta -= HEADER_SIZE; + mem_free += HEADER_SIZE; } else { - // make chunk as free - chunk->used = 0; - dlist_init(&chunk->free); - px_push_free(chunk); + // make chunk as free + chunk->used = 0; + dlist_init(&chunk->free); + px_push_free(chunk); } } From 9de1edc6bd9cf0f562f48a602671febc04301571 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 7 Oct 2020 20:47:37 -0400 Subject: [PATCH 040/139] Fixed documentation alignment in printf --- kernel/lib/printf.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/kernel/lib/printf.cpp b/kernel/lib/printf.cpp index 6ce11313..73939ce4 100644 --- a/kernel/lib/printf.cpp +++ b/kernel/lib/printf.cpp @@ -42,30 +42,30 @@ Revised May 12, 2000 %[flag][width][.prec][mod][conv] flag: - - left justify, pad right w/ blanks DONE - 0 pad left w/ 0 for numerics DONE - + always print sign, + or - no - ' ' (blank) no - # (???) no + - left justify, pad right w/ blanks DONE + 0 pad left w/ 0 for numerics DONE + + always print sign, + or - no + ' ' (blank) no + # (???) no -width: (field width) DONE +width: (field width) DONE -prec: (precision) no +prec: (precision) no -conv: d,i decimal int DONE - u decimal unsigned DONE - o octal DONE - x,X hex DONE - f,e,g,E,G float no - c char DONE - s string DONE - p ptr DONE +conv: d,i decimal int DONE + u decimal unsigned DONE + o octal DONE + x,X hex DONE + f,e,g,E,G float no + c char DONE + s string DONE + p ptr DONE -mod: N near ptr DONE - F far ptr no - h short (16-bit) int DONE - l long (32-bit) int DONE - L long long (64-bit) int no +mod: N near ptr DONE + F far ptr no + h short (16-bit) int DONE + l long (32-bit) int DONE + L long long (64-bit) int no *****************************************************************************/ /* Assume: width of stack == width of int. Don't use sizeof(char *) or From a043a9d6543953b90219043f77c2fff83228f828 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 7 Oct 2020 22:09:55 -0400 Subject: [PATCH 041/139] Added optimizations to release & fixed debug target --- Makefile | 9 +++++---- kernel/arch/i386/timer.cpp | 2 +- kernel/main.cpp | 4 +++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 44ca709b..947e3b0d 100755 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # TODO: Create seperate makefiles as needed and integrate into one makefile # -.DEFAULT_GOAL := dist/kernel +.DEFAULT_GOAL := release GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" # ***************************** @@ -58,7 +58,6 @@ CFLAGS = \ # them at a later time. For example, paging disable. # CXXFLAGS = \ - -g \ -m32 \ -target i386-none-elf \ -ffreestanding \ @@ -120,11 +119,13 @@ dist/kernel: $(OBJ) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym # Debug build -debug: CXXFLAGS += -DDEBUG -debug: CFLAGS += -DDEBUG +debug: CXXFLAGS += -DDEBUG -g +debug: CFLAGS += -DDEBUG -g debug: dist/kernel # Release build +release: CXXFLAGS += -Ofast -mno-sse -mno-avx +release: CFLAGS += -Ofast -mno-sse -mno-avx release: dist/kernel # ******************************** diff --git a/kernel/arch/i386/timer.cpp b/kernel/arch/i386/timer.cpp index e49e6c0d..2dc068b6 100644 --- a/kernel/arch/i386/timer.cpp +++ b/kernel/arch/i386/timer.cpp @@ -15,7 +15,7 @@ #include static void px_timer_callback(registers_t *regs); -uint32_t tick; +volatile uint32_t tick; /** * Sleep Timer Non-Busy Waiting Idea: diff --git a/kernel/main.cpp b/kernel/main.cpp index a5400a4d..37d6da05 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -73,7 +73,9 @@ extern "C" void px_call_constructors() { * for when a smashed stack is detected. * */ +__attribute__ ((used)) uintptr_t __stack_chk_guard = STACK_CHK_GUARD; +__attribute__ ((used)) extern "C" void __stack_chk_fail(void) { PANIC("Smashed stack detected."); @@ -140,8 +142,8 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma i = -1; break; } + asm volatile("hlt"); i++; - asm("hlt"); } PANIC("Kernel terminated unexpectedly!"); } From 0f9267c42156b9ecf0158c516666dd9b94275e0b Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sun, 11 Oct 2020 16:57:32 -0400 Subject: [PATCH 042/139] Add checks for SSE and enable it if possible It will also show an error message if the CPU does not support SSE. --- Makefile | 6 ++- kernel/arch/i386/boot.s | 44 +++++++++++++++++++--- kernel/dev/tty/tty.cpp | 4 +- kernel/sys/early_panic.cpp | 39 +++++++++++++++++++ sysroot/usr/include/kernel/dev/tty/tty.hpp | 2 + 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 kernel/sys/early_panic.cpp diff --git a/Makefile b/Makefile index 947e3b0d..fbc7e2ed 100755 --- a/Makefile +++ b/Makefile @@ -58,6 +58,8 @@ CFLAGS = \ # them at a later time. For example, paging disable. # CXXFLAGS = \ + -g \ + -O3 \ -m32 \ -target i386-none-elf \ -ffreestanding \ @@ -124,8 +126,8 @@ debug: CFLAGS += -DDEBUG -g debug: dist/kernel # Release build -release: CXXFLAGS += -Ofast -mno-sse -mno-avx -release: CFLAGS += -Ofast -mno-sse -mno-avx +release: CXXFLAGS += -Ofast -mno-avx +release: CFLAGS += -Ofast -mno-avx release: dist/kernel # ******************************** diff --git a/kernel/arch/i386/boot.s b/kernel/arch/i386/boot.s index 5e5d45c1..d60adfcc 100644 --- a/kernel/arch/i386/boot.s +++ b/kernel/arch/i386/boot.s @@ -6,6 +6,8 @@ # function in C++ by telling the compiler they exist "somewhere" .extern px_kernel_main .extern px_call_constructors +# minimal panic function that works in most situations +.extern early_panic .extern _KERNEL_START .extern _KERNEL_END @@ -59,7 +61,8 @@ _start: orl $PAGE_PERM, page_directory xor %eax, %eax - _start.lowmem: + +_start.lowmem: movl %eax, %ecx shrl $PAGE_SHIFT, %ecx andl $0x3ff, %ecx @@ -86,7 +89,8 @@ _start: orl $PAGE_PERM, page_directory(,%edx,4) movl $_KERNEL_START, %eax # the kernel's current virtual start - _start.higher: + +_start.higher: # compute the page table offset # this only works because the two page tables are adjacent movl %eax, %edx @@ -125,12 +129,39 @@ _start: # setup and adjust the stack movl $(stack + STACK_SIZE), %esp + # check if SSE is available + movl $0x1, %eax + cpuid + test $(1<<25), %edx + jnz _start.has_sse + + # panic because no SSE :'( + push $no_sse_msg + call early_panic + + # infinite loop if panic returns + jmp _start.catchfire + +_start.has_sse: + # enable SSE + movl %cr0, %eax + andw $0xFFFB, %ax # clear coprocessor emulation CR0.EM + orw $0x2, %ax # set coprocessor monitoring CR0.MP + movl %eax, %cr0 + movl %cr4, %eax + orw $(3<<9), %ax # set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + movl %eax, %cr4 + + # push kernel main parameters pushl multiboot_magic # Multiboot magic number pushl multiboot_info # Multiboot info structure + # Set NULL stack frame for trace xor %ebp, %ebp + # Enter the high-level kernel. call px_kernel_main + # By this point we should be into the wild world of C++ # So, this should never be called unless the kernel returns _start.catchfire: @@ -139,20 +170,23 @@ _start: .section .early_bss, "aw", @nobits .align 4096 -page_directory: # should also be page aligned (hopefully) +page_directory: # should also be page aligned (hopefully) .space 1024*4 # reserve 1024 DWORDs for our page table pointers lowmem_pt: .space 1024*4 # lowmem identity mappings kernel_pt: .space 1024*4 # our kernel page table mappings pages_pt: - .space 1024*4 # a page table that maps pages that contain page tables + .space 1024*4 # a page table that maps pages that contain page tables -.section .early_data, "aw", @nobits +.section .early_data, "aw" +.align 4 multiboot_magic: .long 0 multiboot_info: .long 0 +no_sse_msg: + .asciz "Error: No SSE support available!" .section .bss, "aw", @nobits .align 4 diff --git a/kernel/dev/tty/tty.cpp b/kernel/dev/tty/tty.cpp index 0e81e5e2..d37d93f3 100644 --- a/kernel/dev/tty/tty.cpp +++ b/kernel/dev/tty/tty.cpp @@ -46,14 +46,14 @@ void px_tty_clear(px_tty_vga_color fore, px_tty_vga_color back) { reset_fore = fore; reset_back = back; volatile uint16_t* where; - uint16_t attrib = (color_back << 4) | (color_fore & 0x0F); + uint16_t attrib = VGA_COLOR(color_back, color_fore); // For each character in each line of the TTY, set to ' '. for (int y = 0; y < X86_TTY_HEIGHT; y++) { for (int x = 0; x < X86_TTY_WIDTH; x++) { // This is a direct write to the BIOS TTY memory. // It is much more efficient than calling putchar(). where = x86_bios_vga_mem + (y * X86_TTY_WIDTH + x); - *where = ' ' | (attrib << 8); + *where = VGA_CHAR(' ', attrib); } } // Reset the cursor position diff --git a/kernel/sys/early_panic.cpp b/kernel/sys/early_panic.cpp new file mode 100644 index 00000000..a5106d0c --- /dev/null +++ b/kernel/sys/early_panic.cpp @@ -0,0 +1,39 @@ +/** + * @file early_panic.cpp + * @author Keeton Feavel (keetonfeavel@cedarville.edu) + * @author Micah Switzer (mswitzer@cedarville.edu) + * @version 0.3 + * @date 2020-10-11 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#include +#include + +extern "C" void +__attribute__ ((section(".early_text"))) +__attribute__ ((optnone)) +early_panic(const char *str) { + volatile uint16_t* where; + int x = 0; + int y = 0; + // For each character in the string + for (int i = 0; str[i] != '\0'; ++i) { + switch(str[i]) { + // Newline + case '\n': + x = 0; + y++; + break; + // Anything else + default: + where = x86_bios_vga_mem + (y * X86_TTY_WIDTH + x); + *where = VGA_CHAR(str[i], VGA_COLOR(VGA_Red, VGA_White)); + x++; + break; + } + } +} + diff --git a/sysroot/usr/include/kernel/dev/tty/tty.hpp b/sysroot/usr/include/kernel/dev/tty/tty.hpp index e5485909..88faa6d8 100644 --- a/sysroot/usr/include/kernel/dev/tty/tty.hpp +++ b/sysroot/usr/include/kernel/dev/tty/tty.hpp @@ -81,6 +81,8 @@ enum px_tty_ansi_color { ANSI_BrightCyan = 96, ANSI_BrightWhite = 97 }; +#define VGA_COLOR(bg, fg) (((bg)<<4)|((fg)&0xF)) +#define VGA_CHAR(ch, co) ((ch)|((co)<<8)) // Coorinate trackers extern uint8_t tty_coords_x; extern uint8_t tty_coords_y; From dc35cd6cde5b1478a9a6b3824a9105f2b14a1885 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 11 Oct 2020 19:24:49 -0400 Subject: [PATCH 043/139] Fixed CXX including debug & release flags --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index fbc7e2ed..301bea5c 100755 --- a/Makefile +++ b/Makefile @@ -58,8 +58,6 @@ CFLAGS = \ # them at a later time. For example, paging disable. # CXXFLAGS = \ - -g \ - -O3 \ -m32 \ -target i386-none-elf \ -ffreestanding \ @@ -126,8 +124,8 @@ debug: CFLAGS += -DDEBUG -g debug: dist/kernel # Release build -release: CXXFLAGS += -Ofast -mno-avx -release: CFLAGS += -Ofast -mno-avx +release: CXXFLAGS += -O3 -mno-avx +release: CFLAGS += -O3 -mno-avx release: dist/kernel # ******************************** From f2885668cc2bc9e4002bf59aeb74c25d802ecea0 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 11 Oct 2020 19:25:05 -0400 Subject: [PATCH 044/139] Early panic now clears the screen before printing --- kernel/sys/early_panic.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/sys/early_panic.cpp b/kernel/sys/early_panic.cpp index a5106d0c..b94780a0 100644 --- a/kernel/sys/early_panic.cpp +++ b/kernel/sys/early_panic.cpp @@ -19,6 +19,13 @@ early_panic(const char *str) { volatile uint16_t* where; int x = 0; int y = 0; + // Clear the screen + for (int i = 0; i < X86_TTY_WIDTH; i++) { + for (int j = 0; j < X86_TTY_HEIGHT; j ++) { + where = x86_bios_vga_mem + (j * X86_TTY_WIDTH + i); + *where = VGA_CHAR(' ', VGA_COLOR(VGA_Black, VGA_White)); + } + } // For each character in the string for (int i = 0; str[i] != '\0'; ++i) { switch(str[i]) { From d1c39fe2f8de226310840593c28f690b964b61b4 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 29 Aug 2020 18:24:05 -0500 Subject: [PATCH 045/139] Add kernel tasks init code --- kernel/arch/i386/tasks.S | 48 +++++++++++++++++++++++ kernel/mem/paging.cpp | 6 +++ kernel/sys/tasks.cpp | 31 +++++++++++++++ sysroot/usr/include/kernel/mem/paging.hpp | 8 +++- sysroot/usr/include/kernel/sys/tasks.hpp | 47 ++++++++++++++++++++++ 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 kernel/arch/i386/tasks.S create mode 100644 kernel/sys/tasks.cpp create mode 100644 sysroot/usr/include/kernel/sys/tasks.hpp diff --git a/kernel/arch/i386/tasks.S b/kernel/arch/i386/tasks.S new file mode 100644 index 00000000..46666dd8 --- /dev/null +++ b/kernel/arch/i386/tasks.S @@ -0,0 +1,48 @@ +struc task + .stack: resd 1 + .page_dir: resd 1 + .next_task: resd 1 + .state: resd 1 +endstruc + +bits 32 +section .text +extern px_current_task +global px_tasks_switch_to +px_tasks_switch_to: + ;Save previous task's state + ;Notes: + ; For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again + ; EIP is already saved on the stack by the caller's "CALL" instruction + ; The task isn't able to change CR3 so it doesn't need to be saved + ; Segment registers are constants (while running kernel code) so they don't need to be saved + push ebx + push esi + push edi + push ebp + + mov edi,[px_current_task] ;edi = address of the previous task's "thread control block" + mov [edi+task.stack],esp ;Save ESP for previous task's kernel stack in the thread's TCB + + ;Load next task's state + mov esi,[esp+(4+1)*4] ;esi = address of the next task's "thread control block" (parameter passed on stack) + mov [px_current_task],esi ;Current task's TCB is the next task TCB + + mov esp,[esi+task.stack] ;Load ESP for next task's kernel stack from the thread's TCB + + ; at this point we are operating under the new task's stack + + mov eax,[esi+task.page_dir] ;eax = address of page directory for next task + ;mov ebx,[esi+TCB.ESP0] ;ebx = address for the top of the next task's kernel stack + ;mov [TSS.ESP0],ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) + mov ecx,cr3 ;ecx = previous task's virtual address space + + cmp eax,ecx ;Does the virtual address space need to being changed? + je .done_virt_addr ; no, virtual address space is the same, so don't reload it and cause TLB flushes + mov cr3,eax ; yes, load the next task's virtual address space +.done_virt_addr: + pop ebp + pop edi + pop esi + pop ebx + ret ;Load next task's EIP from its kernel stack diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 626524d4..3a9e68cb 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -214,6 +214,7 @@ void px_free_page(void *page, uint32_t size) { uint32_t page_count = (size / PAGE_SIZE) + 1; uint32_t page_index = (uint32_t)page >> 12; for (uint32_t i = page_index; i < page_index + page_count; i++) { + // TODO: need locking here (maybe make a paging lock) bitmap_clear_bit(mapped_pages, i); // how much more UN-readable can we make this?? (pls, i need to know...) //*(uint32_t*)((uint32_t)page_tables + i * 4) = 0; @@ -234,3 +235,8 @@ bool px_page_is_present(size_t addr) { // check whether the page is in the bitmap return bitmap_get_bit(mapped_pages, (addr >> 12)); } + +// TODO: maybe enforce access control here in the future +uint32_t px_get_phys_page_dir() { + return page_dir_addr; +} diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp new file mode 100644 index 00000000..17d84ff2 --- /dev/null +++ b/kernel/sys/tasks.cpp @@ -0,0 +1,31 @@ +/** + * @file tasks.cpp + * @author Micah Switzer (mswitzer@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-29 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ +#include +#include +#include +#include // Data type definitions + +px_task_t *px_current_task = NULL; + +void px_tasks_init() +{ + px_task_t *this_task = (px_task_t*)malloc(sizeof(px_task_t)); + if (this_task == NULL) PANIC("Unable to allocate memory for new task struct.\n"); + *this_task = { + .stack_top = 0, + .page_dir = px_get_phys_page_dir(), + .next_task = NULL, + .state = TASK_RUNNING + }; + px_current_task = this_task; +} + +// TODO: code here diff --git a/sysroot/usr/include/kernel/mem/paging.hpp b/sysroot/usr/include/kernel/mem/paging.hpp index 60c34d8b..6d50c575 100644 --- a/sysroot/usr/include/kernel/mem/paging.hpp +++ b/sysroot/usr/include/kernel/mem/paging.hpp @@ -151,5 +151,11 @@ void px_free_page(void *page, uint32_t size); */ bool px_page_is_present(size_t addr); -#endif /* PANIX_MEM_PAGING */ +/** + * @brief Gets the physical address of the current page directory. + * + * @returns the physical address of the current page directory. + */ +uint32_t px_get_phys_page_dir(); +#endif /* PANIX_MEM_PAGING */ diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp new file mode 100644 index 00000000..99448bcf --- /dev/null +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -0,0 +1,47 @@ +/** + * @file tasks.hpp + * @author Micah Switzer (mswitzer@cedarville.edu) + * @brief + * @version 0.3 + * @date 2020-08-29 + * + * @copyright Copyright the Panix Contributors (c) 2020 + * + */ + +#ifndef PANIX_TASKS_HPP +#define PANIX_TASKS_HPP + +#include // Data type definitions +#include // Architecture specific features +#include + +enum px_task_state { + TASK_RUNNING, + TASK_BLOCKED, + TASK_STOPPED, + TASK_PAUSED +}; + +typedef struct px_task px_task_t; + +struct px_task +{ + uintptr_t stack_top; + uintptr_t page_dir; + px_task_t *next_task; + px_task_state state; +}; + +extern px_task_t *px_current_task; + +void px_tasks_init(); +#ifdef CPLUSPLUS +extern "C" { +error +#endif +void px_tasks_switch_to(px_task_t *task); +#ifdef CPLUSPLUS +} +#endif +#endif /* PANIX_TASKS_HPP */ From 835fcc5ee35ac826347ed01eb21d4250a4266ba5 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 29 Aug 2020 22:11:15 -0400 Subject: [PATCH 046/139] Implement basic task switching --- Makefile | 2 +- kernel/arch/i386/tasks.S | 4 +- kernel/sys/tasks.cpp | 54 +++++++++++++++++++++++- sysroot/usr/include/kernel/sys/tasks.hpp | 11 ++--- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 301bea5c..1d14b4f7 100755 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ obj/%.o: kernel/%.s obj/%.o: kernel/%.S $(MAKE) mkdir_obj_dirs - $(NASM) -felf -o $@ $< + $(NASM) -f elf32 -o $@ $< # Kernel object dist/kernel: $(OBJ) diff --git a/kernel/arch/i386/tasks.S b/kernel/arch/i386/tasks.S index 46666dd8..86a7db36 100644 --- a/kernel/arch/i386/tasks.S +++ b/kernel/arch/i386/tasks.S @@ -7,8 +7,8 @@ endstruc bits 32 section .text -extern px_current_task -global px_tasks_switch_to +extern px_current_task:data +global px_tasks_switch_to:function px_tasks_switch_to: ;Save previous task's state ;Notes: diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 17d84ff2..384455ce 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -17,15 +17,67 @@ px_task_t *px_current_task = NULL; void px_tasks_init() { + // allocate memory for our task structure px_task_t *this_task = (px_task_t*)malloc(sizeof(px_task_t)); + // panic if the alloc fails (we have no fallback) if (this_task == NULL) PANIC("Unable to allocate memory for new task struct.\n"); *this_task = { + // this will be filled in when we switch to another task for the first time .stack_top = 0, + // this will be the same for kernel tasks .page_dir = px_get_phys_page_dir(), + // there are no other tasks yet .next_task = NULL, + // this task is currently running .state = TASK_RUNNING }; + // this is the current task px_current_task = this_task; } -// TODO: code here +static void _px_tasks_task_starting() +{ + asm("nop"); + // this is called whenever a new task is about to start + // it is run in the context of the new task +} + +// emulate a stack push +// this makes it easier and more intuitive to set up stacks +static inline void _px_stack_push_word(void **stack_pointer, size_t value) +{ + // decrement the stack pointer + *(uintptr_t*)stack_pointer -= sizeof(size_t); + // place the new value at that new address + **(size_t**)stack_pointer = value; +} + +px_task_t *px_tasks_new(void (*entry)(void)) +{ + // allocate memory for our task structure + px_task_t *new_task = (px_task_t*)malloc(sizeof(px_task_t)); + // panic if the alloc fails (we have no fallback) + if (new_task == NULL) PANIC("Unable to allocate memory for new task struct.\n"); + // allocate a page for this stack (we might change this later) + uint8_t *stack = (uint8_t *)px_get_new_page(PAGE_SIZE - 1); + if (stack == NULL) PANIC("Unable to allocate memory for new task stack.\n"); + // remember, the stack grows up + void *stack_pointer = stack + PAGE_SIZE; + // last entry is the final function to call (the start of the task) + _px_stack_push_word(&stack_pointer, (size_t)entry); + // when this task is started, the CPU will pop off this value which will become the new EIP + // we push this function to allow some setup code to be run from within the context of the new task + _px_stack_push_word(&stack_pointer, (size_t)_px_tasks_task_starting); + // our task switching code is going to pop four values off of the stack before returning + _px_stack_push_word(&stack_pointer, 0); + _px_stack_push_word(&stack_pointer, 0); + _px_stack_push_word(&stack_pointer, 0); + _px_stack_push_word(&stack_pointer, 0); + *new_task = { + .stack_top = (uintptr_t)stack_pointer, + .page_dir = px_get_phys_page_dir(), + .next_task = NULL, + .state = TASK_PAUSED + }; + return new_task; +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 99448bcf..9b9a352f 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -36,12 +36,7 @@ struct px_task extern px_task_t *px_current_task; void px_tasks_init(); -#ifdef CPLUSPLUS -extern "C" { -error -#endif -void px_tasks_switch_to(px_task_t *task); -#ifdef CPLUSPLUS -} -#endif +extern "C" void px_tasks_switch_to(px_task_t *task); +px_task_t *px_tasks_new(void (*entry)(void)); + #endif /* PANIX_TASKS_HPP */ From 64c3a2fa92f8b9eefd51dd887b48ae0ef4e1fb85 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 29 Aug 2020 22:45:01 -0400 Subject: [PATCH 047/139] Add basic cooperative, round-robin scheduler --- kernel/sys/tasks.cpp | 17 +++++++++++++++-- sysroot/usr/include/kernel/sys/tasks.hpp | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 384455ce..a7398cb7 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -26,8 +26,8 @@ void px_tasks_init() .stack_top = 0, // this will be the same for kernel tasks .page_dir = px_get_phys_page_dir(), - // there are no other tasks yet - .next_task = NULL, + // this is a circularly-linked list with only this task + .next_task = this_task, // this task is currently running .state = TASK_RUNNING }; @@ -52,6 +52,13 @@ static inline void _px_stack_push_word(void **stack_pointer, size_t value) **(size_t**)stack_pointer = value; } +static void _px_tasks_insert_after_current(px_task_t *task) +{ + px_task_t *temp = px_current_task->next_task; + px_current_task->next_task = task; + task->next_task = temp; +} + px_task_t *px_tasks_new(void (*entry)(void)) { // allocate memory for our task structure @@ -79,5 +86,11 @@ px_task_t *px_tasks_new(void (*entry)(void)) .next_task = NULL, .state = TASK_PAUSED }; + _px_tasks_insert_after_current(new_task); return new_task; } + +void px_tasks_schedule() +{ + px_tasks_switch_to(px_current_task->next_task); +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 9b9a352f..4e23b8be 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -38,5 +38,6 @@ extern px_task_t *px_current_task; void px_tasks_init(); extern "C" void px_tasks_switch_to(px_task_t *task); px_task_t *px_tasks_new(void (*entry)(void)); +void px_tasks_schedule(); #endif /* PANIX_TASKS_HPP */ From 304eca60b2fddd55a99e207410c3614c40fe4c86 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 29 Aug 2020 23:49:56 -0400 Subject: [PATCH 048/139] Add time accounting to task switching --- kernel/arch/i386/tasks.S | 1 + kernel/sys/tasks.cpp | 31 +++++++++++++++++++++--- sysroot/usr/include/kernel/sys/tasks.hpp | 2 ++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/kernel/arch/i386/tasks.S b/kernel/arch/i386/tasks.S index 86a7db36..1b5664e3 100644 --- a/kernel/arch/i386/tasks.S +++ b/kernel/arch/i386/tasks.S @@ -3,6 +3,7 @@ struc task .page_dir: resd 1 .next_task: resd 1 .state: resd 1 + .time_used: resq 1 endstruc bits 32 diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index a7398cb7..854996c1 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -12,8 +12,15 @@ #include #include #include // Data type definitions +// this is a literal hack to specifically circumvent validation checks +// it seems to work fine for the specific intrinsic we need +// we should probably investigate this further at some point... +#define _X86INTRIN_H_INCLUDED +#include // needed for __rdtsc +#undef _X86INTRIN_H_INCLUDED px_task_t *px_current_task = NULL; +static uint64_t _last_time = 0; void px_tasks_init() { @@ -29,15 +36,17 @@ void px_tasks_init() // this is a circularly-linked list with only this task .next_task = this_task, // this task is currently running - .state = TASK_RUNNING + .state = TASK_RUNNING, + // just say that this task hasn't spent any time running yet + .time_used = 0 }; + _last_time = __rdtsc(); // this is the current task px_current_task = this_task; } static void _px_tasks_task_starting() { - asm("nop"); // this is called whenever a new task is about to start // it is run in the context of the new task } @@ -84,13 +93,29 @@ px_task_t *px_tasks_new(void (*entry)(void)) .stack_top = (uintptr_t)stack_pointer, .page_dir = px_get_phys_page_dir(), .next_task = NULL, - .state = TASK_PAUSED + .state = TASK_PAUSED, + .time_used = 0 }; _px_tasks_insert_after_current(new_task); return new_task; } +void px_tasks_update_time() +{ + uint64_t current_time = __rdtsc(); + uint64_t delta = current_time - _last_time; + px_current_task->time_used += delta; + _last_time = current_time; +} + void px_tasks_schedule() { + px_tasks_update_time(); px_tasks_switch_to(px_current_task->next_task); } + +uint64_t px_tasks_get_self_time() +{ + px_tasks_update_time(); + return px_current_task->time_used; +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 4e23b8be..4c715859 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -31,6 +31,7 @@ struct px_task uintptr_t page_dir; px_task_t *next_task; px_task_state state; + uint64_t time_used; }; extern px_task_t *px_current_task; @@ -39,5 +40,6 @@ void px_tasks_init(); extern "C" void px_tasks_switch_to(px_task_t *task); px_task_t *px_tasks_new(void (*entry)(void)); void px_tasks_schedule(); +uint64_t px_tasks_get_self_time(); #endif /* PANIX_TASKS_HPP */ From 3e82e1a031cfe0db039911aa59068010e97a01a7 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sun, 30 Aug 2020 12:35:35 -0400 Subject: [PATCH 049/139] Add support for a ready-list of tasks --- kernel/arch/i386/tasks.S | 15 ++++++- kernel/sys/tasks.cpp | 54 ++++++++++++++++++++---- sysroot/usr/include/kernel/sys/tasks.hpp | 1 + 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/kernel/arch/i386/tasks.S b/kernel/arch/i386/tasks.S index 1b5664e3..6afab668 100644 --- a/kernel/arch/i386/tasks.S +++ b/kernel/arch/i386/tasks.S @@ -6,9 +6,13 @@ struc task .time_used: resq 1 endstruc +%define TASK_RUNNING 0 +%define TASK_READY 1 + bits 32 section .text -extern px_current_task:data +extern px_current_task:data, px_tasks_ready_tail:data +extern _px_tasks_enqueue_ready:function global px_tasks_switch_to:function px_tasks_switch_to: ;Save previous task's state @@ -24,7 +28,13 @@ px_tasks_switch_to: mov edi,[px_current_task] ;edi = address of the previous task's "thread control block" mov [edi+task.stack],esp ;Save ESP for previous task's kernel stack in the thread's TCB - + cmp dword [edi+task.state],TASK_RUNNING + jne .state_updated + mov dword [edi+task.state],TASK_READY ;Set the task's state to ready (from running) + push edi ; push the task to be enqueued + call _px_tasks_enqueue_ready ; call the enqueue function + add esp,4 ; fix up the stack + .state_updated: ;Load next task's state mov esi,[esp+(4+1)*4] ;esi = address of the next task's "thread control block" (parameter passed on stack) mov [px_current_task],esi ;Current task's TCB is the next task TCB @@ -33,6 +43,7 @@ px_tasks_switch_to: ; at this point we are operating under the new task's stack + mov dword [esi+task.state],TASK_RUNNING ;this task is now running mov eax,[esi+task.page_dir] ;eax = address of page directory for next task ;mov ebx,[esi+TCB.ESP0] ;ebx = address for the top of the next task's kernel stack ;mov [TSS.ESP0],ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 854996c1..d608b775 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -20,6 +20,9 @@ #undef _X86INTRIN_H_INCLUDED px_task_t *px_current_task = NULL; +px_task_t *px_tasks_ready_head = NULL; +px_task_t *px_tasks_ready_tail = NULL; + static uint64_t _last_time = 0; void px_tasks_init() @@ -33,8 +36,8 @@ void px_tasks_init() .stack_top = 0, // this will be the same for kernel tasks .page_dir = px_get_phys_page_dir(), - // this is a circularly-linked list with only this task - .next_task = this_task, + // this is a linked list with only this task + .next_task = NULL, // this task is currently running .state = TASK_RUNNING, // just say that this task hasn't spent any time running yet @@ -61,11 +64,38 @@ static inline void _px_stack_push_word(void **stack_pointer, size_t value) **(size_t**)stack_pointer = value; } -static void _px_tasks_insert_after_current(px_task_t *task) +extern "C" void _px_tasks_enqueue_ready(px_task_t *task) +{ + if (px_tasks_ready_head == NULL) { + px_tasks_ready_head = task; + } + if (px_tasks_ready_tail != NULL) { + // the current last task's next pointer will be this task + px_tasks_ready_tail->next_task = task; + } + // and now this task becomes the last task + px_tasks_ready_tail = task; +} + +static px_task_t *_px_tasks_dequeue_ready() { - px_task_t *temp = px_current_task->next_task; - px_current_task->next_task = task; - task->next_task = temp; + px_task_t *task; + if (px_tasks_ready_head == NULL) { + // can't dequeue if there's not anything there + return NULL; + } + // the head of the list is the next item + task = px_tasks_ready_head; + // the new head is the next task + px_tasks_ready_head = task->next_task; + if (px_tasks_ready_head == NULL) { + // if there are no more items in the list, then + // the last item in the list will also be null + px_tasks_ready_tail = NULL; + } + // it doesn't make sense to have a next_task when it's not in a list + task->next_task = NULL; + return task; } px_task_t *px_tasks_new(void (*entry)(void)) @@ -93,10 +123,10 @@ px_task_t *px_tasks_new(void (*entry)(void)) .stack_top = (uintptr_t)stack_pointer, .page_dir = px_get_phys_page_dir(), .next_task = NULL, - .state = TASK_PAUSED, + .state = TASK_READY, .time_used = 0 }; - _px_tasks_insert_after_current(new_task); + _px_tasks_enqueue_ready(new_task); return new_task; } @@ -110,8 +140,14 @@ void px_tasks_update_time() void px_tasks_schedule() { + // get the next task + px_task_t *task = _px_tasks_dequeue_ready(); + // don't need to do anything if there's nothing ready to run + if (task == NULL) return; + // do time accounting px_tasks_update_time(); - px_tasks_switch_to(px_current_task->next_task); + // switch to the task + px_tasks_switch_to(task); } uint64_t px_tasks_get_self_time() diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 4c715859..a0ada176 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -18,6 +18,7 @@ enum px_task_state { TASK_RUNNING, + TASK_READY, TASK_BLOCKED, TASK_STOPPED, TASK_PAUSED From 92976f145785316e66b9f34a7b48522b7fd8ad06 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sun, 30 Aug 2020 13:05:03 -0400 Subject: [PATCH 050/139] Implement crude locking on task scheduling --- kernel/sys/tasks.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index d608b775..bea3c71b 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -24,6 +24,21 @@ px_task_t *px_tasks_ready_head = NULL; px_task_t *px_tasks_ready_tail = NULL; static uint64_t _last_time = 0; +static size_t _scheduler_lock = 0; + +static void _aquire_scheduler_lock() +{ + asm volatile("cli"); + _scheduler_lock++; +} + +static void _release_scheduler_lock() +{ + _scheduler_lock--; + if (_scheduler_lock == 0) { + asm volatile("sti"); + } +} void px_tasks_init() { @@ -52,6 +67,9 @@ static void _px_tasks_task_starting() { // this is called whenever a new task is about to start // it is run in the context of the new task + + // the task before this caused the scheduler to lock + _release_scheduler_lock(); } // emulate a stack push @@ -140,14 +158,19 @@ void px_tasks_update_time() void px_tasks_schedule() { + // we must lock on all scheduling operations + _aquire_scheduler_lock(); // get the next task px_task_t *task = _px_tasks_dequeue_ready(); // don't need to do anything if there's nothing ready to run - if (task == NULL) return; + if (task == NULL) goto done; // do time accounting px_tasks_update_time(); // switch to the task px_tasks_switch_to(task); +done: + // this will run when we switch back to the calling task + _release_scheduler_lock(); } uint64_t px_tasks_get_self_time() From 550f634bb6a8affb2e0b76b000fcbdd4760fca05 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sun, 30 Aug 2020 13:37:43 -0400 Subject: [PATCH 051/139] Implement support for blocking and unblocking tasks --- kernel/sys/tasks.cpp | 52 ++++++++++++++++++++---- sysroot/usr/include/kernel/sys/tasks.hpp | 2 + 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index bea3c71b..11040570 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -63,7 +63,7 @@ void px_tasks_init() px_current_task = this_task; } -static void _px_tasks_task_starting() +static void _task_starting() { // this is called whenever a new task is about to start // it is run in the context of the new task @@ -72,6 +72,14 @@ static void _px_tasks_task_starting() _release_scheduler_lock(); } +static void _task_stopping() +{ + // this is called whenever a task is about to stop (i.e. it returned) + // it is run in the context of the stopping task + px_tasks_block_current(TASK_STOPPED); + PANIC("Attempted to schedule a stopped task\n"); +} + // emulate a stack push // this makes it easier and more intuitive to set up stacks static inline void _px_stack_push_word(void **stack_pointer, size_t value) @@ -127,11 +135,15 @@ px_task_t *px_tasks_new(void (*entry)(void)) if (stack == NULL) PANIC("Unable to allocate memory for new task stack.\n"); // remember, the stack grows up void *stack_pointer = stack + PAGE_SIZE; - // last entry is the final function to call (the start of the task) + // a null stack frame to make the panic screen happy + _px_stack_push_word(&stack_pointer, 0); + // the last thing to happen is the task stopping function + _px_stack_push_word(&stack_pointer, (size_t)_task_stopping); + // next entry is the main function to call (the start of the task) _px_stack_push_word(&stack_pointer, (size_t)entry); // when this task is started, the CPU will pop off this value which will become the new EIP // we push this function to allow some setup code to be run from within the context of the new task - _px_stack_push_word(&stack_pointer, (size_t)_px_tasks_task_starting); + _px_stack_push_word(&stack_pointer, (size_t)_task_starting); // our task switching code is going to pop four values off of the stack before returning _px_stack_push_word(&stack_pointer, 0); _px_stack_push_word(&stack_pointer, 0); @@ -156,19 +168,24 @@ void px_tasks_update_time() _last_time = current_time; } -void px_tasks_schedule() +static void _schedule() { - // we must lock on all scheduling operations - _aquire_scheduler_lock(); // get the next task px_task_t *task = _px_tasks_dequeue_ready(); // don't need to do anything if there's nothing ready to run - if (task == NULL) goto done; + if (task == NULL) return; // do time accounting px_tasks_update_time(); // switch to the task px_tasks_switch_to(task); -done: +} + +void px_tasks_schedule() +{ + // we must lock on all scheduling operations + _aquire_scheduler_lock(); + // run the scheduler + _schedule(); // this will run when we switch back to the calling task _release_scheduler_lock(); } @@ -178,3 +195,22 @@ uint64_t px_tasks_get_self_time() px_tasks_update_time(); return px_current_task->time_used; } + +void px_tasks_block_current(px_task_state reason) +{ + _aquire_scheduler_lock(); + px_current_task->state = reason; + _schedule(); + _release_scheduler_lock(); +} + +void px_tasks_unblock(px_task_t *task) +{ + _aquire_scheduler_lock(); + if (px_tasks_ready_head == NULL) { + px_tasks_switch_to(task); + } else { + _px_tasks_enqueue_ready(task); + } + _release_scheduler_lock(); +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index a0ada176..2b9611b0 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -42,5 +42,7 @@ extern "C" void px_tasks_switch_to(px_task_t *task); px_task_t *px_tasks_new(void (*entry)(void)); void px_tasks_schedule(); uint64_t px_tasks_get_self_time(); +void px_tasks_block_current(px_task_state reason); +void px_tasks_unblock(px_task_t *task); #endif /* PANIX_TASKS_HPP */ From a179fe3325baba0e19c0b106445e670145ad9f35 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 31 Aug 2020 21:21:50 -0400 Subject: [PATCH 052/139] Change linker to GCC --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1d14b4f7..c4548084 100755 --- a/Makefile +++ b/Makefile @@ -79,8 +79,8 @@ CPP_FLAGS = \ # Assembler flags AS_FLAGS = --32 # Linker flags -LD_FLAGS = -m elf_i386 \ - -T kernel/arch/i386/linker.ld +LD_FLAGS = -T kernel/arch/i386/linker.ld + # *********************************** # * Source Code Compilation Targets * @@ -115,7 +115,7 @@ obj/%.o: kernel/%.S # Kernel object dist/kernel: $(OBJ) @ mkdir -p dist - $(LD) $(LD_FLAGS) -o $@ $(OBJ) + $(CXX) $(LD_FLAGS) -o $@ $(OBJ) $(CXXFLAGS) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym # Debug build From b066a0ce91a2ef21e6c1a4530b41c40cdec0ee1b Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 31 Aug 2020 21:23:56 -0400 Subject: [PATCH 053/139] Change time accounting to use real time (microseconds) --- kernel/arch/i386/timer.cpp | 14 +++++------ kernel/sys/tasks.cpp | 24 +++++++++++++++++-- .../usr/include/kernel/arch/i386/timer.hpp | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/kernel/arch/i386/timer.cpp b/kernel/arch/i386/timer.cpp index 2dc068b6..53bf1cce 100644 --- a/kernel/arch/i386/timer.cpp +++ b/kernel/arch/i386/timer.cpp @@ -15,13 +15,13 @@ #include static void px_timer_callback(registers_t *regs); -volatile uint32_t tick; +volatile uint32_t px_timer_tick; /** * Sleep Timer Non-Busy Waiting Idea: * Create a struct that contains the end time and the callback - * function pointer that should be called when tick = end - * After each tick we check our end time and call the function + * function pointer that should be called when px_timer_tick = end + * After each px_timer_tick we check our end time and call the function * if we're equal. */ @@ -41,18 +41,18 @@ void px_timer_init(uint32_t freq) { } static void px_timer_callback(registers_t *regs) { - tick++; + px_timer_tick++; } void px_timer_print() { - px_kprintf(DBG_INFO "Tick: %i\n", tick); + px_kprintf(DBG_INFO "Tick: %i\n", px_timer_tick); } void sleep(uint32_t ms) { - uint32_t start = tick; + uint32_t start = px_timer_tick; uint32_t final = start + ms; // Waste CPU cycles like a slob - while (tick != final); + while (px_timer_tick != final); // Return now that we've waited long enough return; } \ No newline at end of file diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 11040570..ba5137e7 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -19,12 +19,15 @@ #include // needed for __rdtsc #undef _X86INTRIN_H_INCLUDED +#include + px_task_t *px_current_task = NULL; px_task_t *px_tasks_ready_head = NULL; px_task_t *px_tasks_ready_tail = NULL; static uint64_t _last_time = 0; static size_t _scheduler_lock = 0; +static uint64_t _instr_per_ns; static void _aquire_scheduler_lock() { @@ -40,12 +43,28 @@ static void _release_scheduler_lock() } } +static void _discover_cpu_speed() +{ + uint32_t curr_tick = px_timer_tick; + uint64_t curr_rtsc = __rdtsc(); + while (px_timer_tick != curr_tick + 1) { } + curr_rtsc = __rdtsc() - curr_rtsc; + _instr_per_ns = curr_rtsc / 1000000; +} + +static inline uint64_t _get_cpu_time_ns() +{ + return (__rdtsc()) / _instr_per_ns; +} + void px_tasks_init() { // allocate memory for our task structure px_task_t *this_task = (px_task_t*)malloc(sizeof(px_task_t)); // panic if the alloc fails (we have no fallback) if (this_task == NULL) PANIC("Unable to allocate memory for new task struct.\n"); + // discover the CPU speed for accurate scheduling + _discover_cpu_speed(); *this_task = { // this will be filled in when we switch to another task for the first time .stack_top = 0, @@ -58,7 +77,7 @@ void px_tasks_init() // just say that this task hasn't spent any time running yet .time_used = 0 }; - _last_time = __rdtsc(); + _last_time = _get_cpu_time_ns(); // this is the current task px_current_task = this_task; } @@ -77,6 +96,7 @@ static void _task_stopping() // this is called whenever a task is about to stop (i.e. it returned) // it is run in the context of the stopping task px_tasks_block_current(TASK_STOPPED); + // prevent undefined behavior from returning to a random address PANIC("Attempted to schedule a stopped task\n"); } @@ -162,7 +182,7 @@ px_task_t *px_tasks_new(void (*entry)(void)) void px_tasks_update_time() { - uint64_t current_time = __rdtsc(); + uint64_t current_time = _get_cpu_time_ns(); uint64_t delta = current_time - _last_time; px_current_task->time_used += delta; _last_time = current_time; diff --git a/sysroot/usr/include/kernel/arch/i386/timer.hpp b/sysroot/usr/include/kernel/arch/i386/timer.hpp index 17484cf4..ea79dd75 100644 --- a/sysroot/usr/include/kernel/arch/i386/timer.hpp +++ b/sysroot/usr/include/kernel/arch/i386/timer.hpp @@ -17,6 +17,8 @@ #define TIMER_COMMAND_PORT 0x43 #define TIMER_DATA_PORT 0x40 +extern uint32_t px_timer_tick; + /** * @brief Initialize the CPU timer with the given frequency. * From 7bd5e9ec939f161726b51cfe23cb086ceeb42eb2 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 7 Sep 2020 20:50:29 -0400 Subject: [PATCH 054/139] Add support for PIT callbacks --- kernel/arch/i386/timer.cpp | 18 +++++++++++++++++- sysroot/usr/include/kernel/arch/i386/timer.hpp | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/kernel/arch/i386/timer.cpp b/kernel/arch/i386/timer.cpp index 53bf1cce..1ed7c6eb 100644 --- a/kernel/arch/i386/timer.cpp +++ b/kernel/arch/i386/timer.cpp @@ -17,6 +17,12 @@ static void px_timer_callback(registers_t *regs); volatile uint32_t px_timer_tick; +typedef void (*voidfunc_t)(); + +#define MAX_CALLBACKS 8 +static size_t _callback_count = 0; +static voidfunc_t _callbacks[MAX_CALLBACKS]; + /** * Sleep Timer Non-Busy Waiting Idea: * Create a struct that contains the end time and the callback @@ -42,6 +48,9 @@ void px_timer_init(uint32_t freq) { static void px_timer_callback(registers_t *regs) { px_timer_tick++; + for (size_t i = 0; i < _callback_count; i++) { + _callbacks[i](); + } } void px_timer_print() { @@ -55,4 +64,11 @@ void sleep(uint32_t ms) { while (px_timer_tick != final); // Return now that we've waited long enough return; -} \ No newline at end of file +} + +void px_timer_register_callback(void (*func)()) { + if (_callback_count < MAX_CALLBACKS - 1) { + _callbacks[_callback_count] = func; + _callback_count++; + } +} diff --git a/sysroot/usr/include/kernel/arch/i386/timer.hpp b/sysroot/usr/include/kernel/arch/i386/timer.hpp index ea79dd75..113277a1 100644 --- a/sysroot/usr/include/kernel/arch/i386/timer.hpp +++ b/sysroot/usr/include/kernel/arch/i386/timer.hpp @@ -37,4 +37,6 @@ void px_timer_print(); */ void sleep(uint32_t ms); +void px_timer_register_callback(void (*func)()); + #endif /* PANIX_I386_TIMER_HPP */ \ No newline at end of file From a7e8a091baf30c4c515e5fb3f70cfbad8a9adeb9 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 7 Sep 2020 20:57:11 -0400 Subject: [PATCH 055/139] Abstract task lists --- kernel/sys/tasks.cpp | 73 +++++++++++++++++++----- sysroot/usr/include/kernel/sys/tasks.hpp | 7 +++ 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index ba5137e7..f6caf451 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -22,8 +22,9 @@ #include px_task_t *px_current_task = NULL; -px_task_t *px_tasks_ready_head = NULL; -px_task_t *px_tasks_ready_tail = NULL; + +px_tasklist_t px_tasks_ready = { 0 }; +px_tasklist_t px_tasks_sleeping = { 0 }; static uint64_t _last_time = 0; static size_t _scheduler_lock = 0; @@ -110,40 +111,82 @@ static inline void _px_stack_push_word(void **stack_pointer, size_t value) **(size_t**)stack_pointer = value; } -extern "C" void _px_tasks_enqueue_ready(px_task_t *task) +static void _enqueue_task(px_tasklist_t *list, px_task *task) { - if (px_tasks_ready_head == NULL) { - px_tasks_ready_head = task; + if (list->head == NULL) { + list->head = task; } - if (px_tasks_ready_tail != NULL) { + if (list->tail != NULL) { // the current last task's next pointer will be this task - px_tasks_ready_tail->next_task = task; + list->tail->next_task = task; } // and now this task becomes the last task - px_tasks_ready_tail = task; + list->tail = task; } -static px_task_t *_px_tasks_dequeue_ready() +static px_task_t *_dequeue_task(px_tasklist_t *list) { px_task_t *task; - if (px_tasks_ready_head == NULL) { + if (list->head == NULL) { // can't dequeue if there's not anything there return NULL; } // the head of the list is the next item - task = px_tasks_ready_head; + task = list->head; // the new head is the next task - px_tasks_ready_head = task->next_task; - if (px_tasks_ready_head == NULL) { + list->head = task->next_task; + if (list->head == NULL) { // if there are no more items in the list, then // the last item in the list will also be null - px_tasks_ready_tail = NULL; + list->tail = NULL; } // it doesn't make sense to have a next_task when it's not in a list task->next_task = NULL; return task; } +static void _remove_task(px_tasklist_t *list, px_task_t *task, px_task_t *previous) +{ + // if this is true, something's not right... + if (previous != NULL && previous->next_task != task) { + PANIC("Bogus arguments to _remove_task.\n"); + } + // update the head if necessary + if (list->head == task) { + list->head = task->next_task; + } + // update the tail if necessary + if (list->tail == task) { + list->tail = previous; + } + // update the previous task if necessary + if (previous != NULL) { + previous->next_task = task->next_task; + } + // it's not in any list anymore, so clear its next pointer + task->next_task = NULL; +} + +extern "C" void _px_tasks_enqueue_ready(px_task_t *task) +{ + _enqueue_task(&px_tasks_ready, task); +} + +static px_task_t *_px_tasks_dequeue_ready() +{ + return _dequeue_task(&px_tasks_ready); +} + +static void _enqueue_sleeping(px_task_t *task) +{ + _enqueue_task(&px_tasks_sleeping, task); +} + +static px_task_t *_dequeue_sleeping() +{ + return _dequeue_task(&px_tasks_sleeping); +} + px_task_t *px_tasks_new(void (*entry)(void)) { // allocate memory for our task structure @@ -227,7 +270,7 @@ void px_tasks_block_current(px_task_state reason) void px_tasks_unblock(px_task_t *task) { _aquire_scheduler_lock(); - if (px_tasks_ready_head == NULL) { + if (px_tasks_ready.head == NULL) { px_tasks_switch_to(task); } else { _px_tasks_enqueue_ready(task); diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 2b9611b0..659fa676 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -35,6 +35,13 @@ struct px_task uint64_t time_used; }; +typedef struct px_tasklist +{ + px_task_t *head; + px_task_t *tail; +} px_tasklist_t; + + extern px_task_t *px_current_task; void px_tasks_init(); From 831b47681435da05e1ddf70389b431f6a85efc3f Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 7 Sep 2020 21:01:48 -0400 Subject: [PATCH 056/139] Implement task nano sleep --- kernel/sys/tasks.cpp | 50 ++++++++++++++++++++++++ sysroot/usr/include/kernel/sys/tasks.hpp | 8 +++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index f6caf451..8c5b7bf0 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -51,6 +51,8 @@ static void _discover_cpu_speed() while (px_timer_tick != curr_tick + 1) { } curr_rtsc = __rdtsc() - curr_rtsc; _instr_per_ns = curr_rtsc / 1000000; + // will be inaccurate, but it's the best we can do in these circumstances + if (_instr_per_ns == 0) _instr_per_ns = 1; } static inline uint64_t _get_cpu_time_ns() @@ -58,6 +60,8 @@ static inline uint64_t _get_cpu_time_ns() return (__rdtsc()) / _instr_per_ns; } +static void _on_timer(); + void px_tasks_init() { // allocate memory for our task structure @@ -81,6 +85,7 @@ void px_tasks_init() _last_time = _get_cpu_time_ns(); // this is the current task px_current_task = this_task; + px_timer_register_callback(_on_timer); } static void _task_starting() @@ -277,3 +282,48 @@ void px_tasks_unblock(px_task_t *task) } _release_scheduler_lock(); } + +void _wakeup(px_task_t *task) +{ + task->state = TASK_READY; + task->wakeup_time = (0ULL - 1); + _px_tasks_enqueue_ready(task); +} + +static void _on_timer() +{ + _aquire_scheduler_lock(); + px_task_t *pre = NULL; + px_task_t *task = px_tasks_sleeping.head; + bool need_schedule = false; + uint64_t time = _get_cpu_time_ns(); + while (task != NULL) { + if (time >= task->wakeup_time) { + _remove_task(&px_tasks_sleeping, task, pre); + _wakeup(task); + need_schedule = true; + } + pre = task; + task = task->next_task; + } + if (need_schedule) { + _schedule(); + } + _release_scheduler_lock(); +} + +void px_tasks_nano_sleep_until(uint64_t time) +{ + // TODO: maybe validate that this time is in the future? + _aquire_scheduler_lock(); + px_current_task->state = TASK_SLEEPING; + px_current_task->wakeup_time = time; + _enqueue_sleeping(px_current_task); + _schedule(); + _release_scheduler_lock(); +} + +void px_tasks_nano_sleep(uint64_t time) +{ + px_tasks_nano_sleep_until(_get_cpu_time_ns() + time); +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 659fa676..194b6322 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -17,8 +17,9 @@ #include enum px_task_state { - TASK_RUNNING, - TASK_READY, + TASK_RUNNING = 0, + TASK_READY = 1, + TASK_SLEEPING, TASK_BLOCKED, TASK_STOPPED, TASK_PAUSED @@ -33,6 +34,7 @@ struct px_task px_task_t *next_task; px_task_state state; uint64_t time_used; + uint64_t wakeup_time; }; typedef struct px_tasklist @@ -51,5 +53,7 @@ void px_tasks_schedule(); uint64_t px_tasks_get_self_time(); void px_tasks_block_current(px_task_state reason); void px_tasks_unblock(px_task_t *task); +void px_tasks_nano_sleep_until(uint64_t time); +void px_tasks_nano_sleep(uint64_t time); #endif /* PANIX_TASKS_HPP */ From a4395211d2fa9ac3445312d5bb9e6cc41679ed88 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 28 Sep 2020 21:19:55 -0400 Subject: [PATCH 057/139] Implement idling for tasks --- kernel/sys/tasks.cpp | 49 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 8c5b7bf0..ba9d9551 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -11,6 +11,8 @@ #include #include #include +#include + #include // Data type definitions // this is a literal hack to specifically circumvent validation checks // it seems to work fine for the specific intrinsic we need @@ -26,6 +28,8 @@ px_task_t *px_current_task = NULL; px_tasklist_t px_tasks_ready = { 0 }; px_tasklist_t px_tasks_sleeping = { 0 }; +static uint64_t _idle_time = 0; +static uint64_t _idle_start = 0; static uint64_t _last_time = 0; static size_t _scheduler_lock = 0; static uint64_t _instr_per_ns; @@ -232,18 +236,55 @@ void px_tasks_update_time() { uint64_t current_time = _get_cpu_time_ns(); uint64_t delta = current_time - _last_time; - px_current_task->time_used += delta; + if (px_current_task == NULL) { + _idle_time += delta; + } else { + px_current_task->time_used += delta; + } _last_time = current_time; } static void _schedule() { + if (px_current_task == NULL) { + // we are currently idling and will schedule at a later time + return; + } // get the next task px_task_t *task = _px_tasks_dequeue_ready(); // don't need to do anything if there's nothing ready to run - if (task == NULL) return; - // do time accounting - px_tasks_update_time(); + if (task == NULL) { + if (px_current_task->state == TASK_RUNNING) { + // still running the same task + return; + } + // count the time that this task ran for + px_tasks_update_time(); + /*** idle ***/ + // borrow this task to return to once we're not idle anymore + px_task_t *borrowed = px_current_task; + // set the current task to null to indicate an idle state + px_current_task = NULL; + //_idle_start = _get_cpu_time_ns(); + do { + // enable interrupts to process timer and other events + asm ("sti"); + // immediately halt the CPU + asm ("hlt"); + // disable interrupts to restore our lock + asm ("cli"); + // check if there's a task ready to be run + } while(task = _px_tasks_dequeue_ready(), task == NULL); + // count the time we spent idling + px_tasks_update_time(); + // reset the current task + px_current_task = borrowed; + //_idle_start = _idle_start - _get_cpu_time_ns(); + //px_kprintf("Slept for %lld nanoseconds.\n", _idle_start); + } else { + // just do time accounting once + px_tasks_update_time(); + } // switch to the task px_tasks_switch_to(task); } From 896a4e56a71ab2a1aa4e04a25499949f56b6226d Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Wed, 7 Oct 2020 20:19:19 -0400 Subject: [PATCH 058/139] Re-add idle time counter --- kernel/sys/tasks.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index ba9d9551..126473de 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -265,7 +265,7 @@ static void _schedule() px_task_t *borrowed = px_current_task; // set the current task to null to indicate an idle state px_current_task = NULL; - //_idle_start = _get_cpu_time_ns(); + _idle_start = _get_cpu_time_ns(); do { // enable interrupts to process timer and other events asm ("sti"); @@ -274,13 +274,14 @@ static void _schedule() // disable interrupts to restore our lock asm ("cli"); // check if there's a task ready to be run - } while(task = _px_tasks_dequeue_ready(), task == NULL); + } while (task = _px_tasks_dequeue_ready(), task == NULL); // count the time we spent idling px_tasks_update_time(); // reset the current task px_current_task = borrowed; - //_idle_start = _idle_start - _get_cpu_time_ns(); - //px_kprintf("Slept for %lld nanoseconds.\n", _idle_start); + _idle_start = _idle_start - _get_cpu_time_ns(); + _idle_time += _idle_start; + px_kprintf("Slept for %lld nanoseconds.\n", _idle_start); } else { // just do time accounting once px_tasks_update_time(); From 075ffeec60160c11a65e1846320c8ef64a3500c9 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Tue, 20 Oct 2020 19:39:02 -0400 Subject: [PATCH 059/139] Make the scheduler pre-emptive --- kernel/sys/tasks.cpp | 36 +++++++++++++++++++++++- sysroot/usr/include/kernel/sys/tasks.hpp | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 126473de..19c60d75 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -31,6 +31,8 @@ px_tasklist_t px_tasks_sleeping = { 0 }; static uint64_t _idle_time = 0; static uint64_t _idle_start = 0; static uint64_t _last_time = 0; +static uint64_t _time_slice_remaining = 0; +static uint64_t _last_timer_time = 0; static size_t _scheduler_lock = 0; static uint64_t _instr_per_ns; @@ -86,7 +88,11 @@ void px_tasks_init() // just say that this task hasn't spent any time running yet .time_used = 0 }; + // update the timer variables _last_time = _get_cpu_time_ns(); + _last_timer_time = _last_time; + // enable time slices + _time_slice_remaining = TIME_SLICE_SIZE; // this is the current task px_current_task = this_task; px_timer_register_callback(_on_timer); @@ -256,8 +262,12 @@ static void _schedule() if (task == NULL) { if (px_current_task->state == TASK_RUNNING) { // still running the same task + // but also reset the time slice counter + _time_slice_remaining = TIME_SLICE_SIZE; return; } + // disable time slices because there are no tasks available to run + _time_slice_remaining = 0; // count the time that this task ran for px_tasks_update_time(); /*** idle ***/ @@ -281,11 +291,14 @@ static void _schedule() px_current_task = borrowed; _idle_start = _idle_start - _get_cpu_time_ns(); _idle_time += _idle_start; - px_kprintf("Slept for %lld nanoseconds.\n", _idle_start); } else { // just do time accounting once px_tasks_update_time(); } + // reset the time slice because a new task is being scheduled + _time_slice_remaining = TIME_SLICE_SIZE; + // reset the last "timer time" since the time slice was reset + _last_timer_time = _get_cpu_time_ns(); // switch to the task px_tasks_switch_to(task); } @@ -335,12 +348,16 @@ void _wakeup(px_task_t *task) static void _on_timer() { _aquire_scheduler_lock(); + px_task_t *pre = NULL; px_task_t *task = px_tasks_sleeping.head; bool need_schedule = false; uint64_t time = _get_cpu_time_ns(); + uint64_t time_delta; + while (task != NULL) { if (time >= task->wakeup_time) { + //px_rs232_print("timer: waking sleeping task\n"); _remove_task(&px_tasks_sleeping, task, pre); _wakeup(task); need_schedule = true; @@ -348,9 +365,25 @@ static void _on_timer() pre = task; task = task->next_task; } + + if (_time_slice_remaining != 0) { + time_delta = time - _last_timer_time; + _last_timer_time = time; + if (time_delta >= _time_slice_remaining) { + // schedule (and maybe pre-empt) + // the schedule function will reset the time slice + //px_rs232_print("timer: time slice expired\n"); + need_schedule = true; + } else { + // decrement the time slice counter + _time_slice_remaining -= time_delta; + } + } + if (need_schedule) { _schedule(); } + _release_scheduler_lock(); } @@ -369,3 +402,4 @@ void px_tasks_nano_sleep(uint64_t time) { px_tasks_nano_sleep_until(_get_cpu_time_ns() + time); } + diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 194b6322..47ada0f4 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -16,6 +16,8 @@ #include // Architecture specific features #include +#define TIME_SLICE_SIZE (1 * 1000 * 1000ULL) + enum px_task_state { TASK_RUNNING = 0, TASK_READY = 1, From b4e4608f74f127e6c6a73914bba537a37fad019d Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Wed, 21 Oct 2020 17:16:51 -0400 Subject: [PATCH 060/139] Use macros to create tasklists --- kernel/sys/tasks.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 19c60d75..ded57015 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -23,10 +23,22 @@ #include +/* forward declarations for macros */ +static void _enqueue_task(px_tasklist_t *, px_task *); +static px_task_t *_dequeue_task(px_tasklist_t *); + +/* macro to create a new named tasklist and associated helper functions */ +#define NAMED_TASKLIST(name) \ + px_tasklist_t px_tasks_##name = { 0 }; \ + static inline void _enqueue_##name(px_task_t *task) { \ + _enqueue_task(&px_tasks_##name, task); } \ + static inline px_task_t *_dequeue_##name() { \ + return _dequeue_task(&px_tasks_##name); } + px_task_t *px_current_task = NULL; px_tasklist_t px_tasks_ready = { 0 }; -px_tasklist_t px_tasks_sleeping = { 0 }; +NAMED_TASKLIST(sleeping); static uint64_t _idle_time = 0; static uint64_t _idle_start = 0; @@ -192,16 +204,6 @@ static px_task_t *_px_tasks_dequeue_ready() return _dequeue_task(&px_tasks_ready); } -static void _enqueue_sleeping(px_task_t *task) -{ - _enqueue_task(&px_tasks_sleeping, task); -} - -static px_task_t *_dequeue_sleeping() -{ - return _dequeue_task(&px_tasks_sleeping); -} - px_task_t *px_tasks_new(void (*entry)(void)) { // allocate memory for our task structure From 3a9511990695dd8b51bc6dce39b6c5c9b643a26a Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Fri, 23 Oct 2020 19:59:34 -0400 Subject: [PATCH 061/139] Add ability to terminate tasks The code was out of control before this. --- kernel/sys/tasks.cpp | 90 ++++++++++++++++++++---- sysroot/usr/include/kernel/sys/tasks.hpp | 3 +- 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index ded57015..31ebfe6f 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -12,7 +12,7 @@ #include #include #include - +#include #include // Data type definitions // this is a literal hack to specifically circumvent validation checks // it seems to work fine for the specific intrinsic we need @@ -23,9 +23,10 @@ #include -/* forward declarations for macros */ +/* forward declarations */ static void _enqueue_task(px_tasklist_t *, px_task *); static px_task_t *_dequeue_task(px_tasklist_t *); +static void _cleaner_task_impl(void); /* macro to create a new named tasklist and associated helper functions */ #define NAMED_TASKLIST(name) \ @@ -36,9 +37,12 @@ static px_task_t *_dequeue_task(px_tasklist_t *); return _dequeue_task(&px_tasks_##name); } px_task_t *px_current_task = NULL; +static px_task_t _cleaner_task; +static px_task_t _first_task; px_tasklist_t px_tasks_ready = { 0 }; NAMED_TASKLIST(sleeping); +NAMED_TASKLIST(stopped); static uint64_t _idle_time = 0; static uint64_t _idle_start = 0; @@ -82,10 +86,8 @@ static void _on_timer(); void px_tasks_init() { - // allocate memory for our task structure - px_task_t *this_task = (px_task_t*)malloc(sizeof(px_task_t)); - // panic if the alloc fails (we have no fallback) - if (this_task == NULL) PANIC("Unable to allocate memory for new task struct.\n"); + // get a pointer to the first task's tcb + px_task_t *this_task = &_first_task; // discover the CPU speed for accurate scheduling _discover_cpu_speed(); *this_task = { @@ -100,6 +102,9 @@ void px_tasks_init() // just say that this task hasn't spent any time running yet .time_used = 0 }; + // create a task for the cleaner and set it's state to "paused" + (void) px_tasks_new(_cleaner_task_impl, &_cleaner_task, TASK_PAUSED); + _cleaner_task.state = TASK_PAUSED; // update the timer variables _last_time = _get_cpu_time_ns(); _last_timer_time = _last_time; @@ -123,7 +128,7 @@ static void _task_stopping() { // this is called whenever a task is about to stop (i.e. it returned) // it is run in the context of the stopping task - px_tasks_block_current(TASK_STOPPED); + px_tasks_exit(); // prevent undefined behavior from returning to a random address PANIC("Attempted to schedule a stopped task\n"); } @@ -204,12 +209,17 @@ static px_task_t *_px_tasks_dequeue_ready() return _dequeue_task(&px_tasks_ready); } -px_task_t *px_tasks_new(void (*entry)(void)) +px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state) { - // allocate memory for our task structure - px_task_t *new_task = (px_task_t*)malloc(sizeof(px_task_t)); - // panic if the alloc fails (we have no fallback) - if (new_task == NULL) PANIC("Unable to allocate memory for new task struct.\n"); + px_task_t *new_task = storage; + if (storage == NULL) { + // allocate memory for our task structure + new_task = (px_task_t*)malloc(sizeof(px_task_t)); + // panic if the alloc fails (we have no fallback) + if (new_task == NULL) { + PANIC("Unable to allocate memory for new task struct.\n"); + } + } // allocate a page for this stack (we might change this later) uint8_t *stack = (uint8_t *)px_get_new_page(PAGE_SIZE - 1); if (stack == NULL) PANIC("Unable to allocate memory for new task stack.\n"); @@ -233,10 +243,12 @@ px_task_t *px_tasks_new(void (*entry)(void)) .stack_top = (uintptr_t)stack_pointer, .page_dir = px_get_phys_page_dir(), .next_task = NULL, - .state = TASK_READY, + .state = state, .time_used = 0 }; - _px_tasks_enqueue_ready(new_task); + if (state == TASK_READY) { + _px_tasks_enqueue_ready(new_task); + } return new_task; } @@ -405,3 +417,53 @@ void px_tasks_nano_sleep(uint64_t time) px_tasks_nano_sleep_until(_get_cpu_time_ns() + time); } +void px_tasks_exit() +{ + char str[32]; + + // userspace cleanup can happen here + px_ksprintf(str, "task 0x%08x exiting.\n", (uint32_t)px_current_task); + px_rs232_print(str); + + _aquire_scheduler_lock(); + // all scheduling-specific operations must happen here + _enqueue_stopped(px_current_task); + + // the ordering of these two should really be reversed + // but the scheduler currently isn't very smart + px_tasks_unblock(&_cleaner_task); + px_tasks_block_current(TASK_STOPPED); + + _release_scheduler_lock(); +} + +static void _clean_stopped_task(px_task_t *task) +{ + // free the stack page + uintptr_t page = task->stack_top & PAGE_ALIGN; + px_free_page((void *)page, PAGE_SIZE - 1); + // somehow determine if the task was dynamically allocated or not + // just assume statically allocated tasks will never exit (bad idea) + free(task); +} + +static void _cleaner_task_impl() +{ + char str[32]; + for (;;) { + px_task_t *task; + _aquire_scheduler_lock(); + + while (px_tasks_stopped.head != NULL) { + task = _dequeue_stopped(); + px_ksprintf(str, "cleaning up task 0x%08x.\n", (uint32_t)task); + px_rs232_print(str); + _clean_stopped_task(task); + } + + _release_scheduler_lock(); + // a schedule occuring at this point would be okay + // it just needs to occur before the loop repeats + px_tasks_block_current(TASK_PAUSED); + } +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 47ada0f4..6b525bd4 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -50,12 +50,13 @@ extern px_task_t *px_current_task; void px_tasks_init(); extern "C" void px_tasks_switch_to(px_task_t *task); -px_task_t *px_tasks_new(void (*entry)(void)); +px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state); void px_tasks_schedule(); uint64_t px_tasks_get_self_time(); void px_tasks_block_current(px_task_state reason); void px_tasks_unblock(px_task_t *task); void px_tasks_nano_sleep_until(uint64_t time); void px_tasks_nano_sleep(uint64_t time); +void px_tasks_exit(void); #endif /* PANIX_TASKS_HPP */ From 114023ab5fa5a26ddbf7aff99cd88963093350f0 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Fri, 23 Oct 2020 21:20:55 -0400 Subject: [PATCH 062/139] Make fixes for Clang --- Makefile | 9 +++++---- kernel/arch/i386/timer.cpp | 2 +- kernel/sys/tasks.cpp | 14 +++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index c4548084..13c528f7 100755 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # Compilers/Assemblers/Linkers AS = $(shell command -v i686-elf-as) -NASM = $(shell command -v llc) +NASM = $(shell command -v nasm) CXX = $(shell command -v clang++) LD = $(shell command -v ld.lld) OBJCP = $(shell command -v llvm-objcopy) @@ -63,6 +63,7 @@ CXXFLAGS = \ -ffreestanding \ -fstack-protector-all \ -fpermissive \ + -nostdlib \ -nodefaultlibs \ -fno-use-cxa-atexit \ -fno-builtin \ @@ -79,7 +80,7 @@ CPP_FLAGS = \ # Assembler flags AS_FLAGS = --32 # Linker flags -LD_FLAGS = -T kernel/arch/i386/linker.ld +LD_FLAGS = -T kernel/arch/i386/linker.ld -nostartfiles -nodefaultlibs -static-libgcc -lgcc # *********************************** @@ -115,7 +116,7 @@ obj/%.o: kernel/%.S # Kernel object dist/kernel: $(OBJ) @ mkdir -p dist - $(CXX) $(LD_FLAGS) -o $@ $(OBJ) $(CXXFLAGS) + $(CXX) -o $@ $(OBJ) $(CXXFLAGS) $(LD_FLAGS) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym # Debug build @@ -187,7 +188,7 @@ debugger: dist/kernel ($(QEMU) \ -S -s \ -kernel $< \ - $(QEMU_FLAGS) &) + $(QEMU_FLAGS) > /dev/null &) sleep 1 wmctrl -xr qemu.Qemu-system-$(QEMU_ARCH) -b add,above # After this start the visual studio debugger diff --git a/kernel/arch/i386/timer.cpp b/kernel/arch/i386/timer.cpp index 1ed7c6eb..9be8e3c8 100644 --- a/kernel/arch/i386/timer.cpp +++ b/kernel/arch/i386/timer.cpp @@ -61,7 +61,7 @@ void sleep(uint32_t ms) { uint32_t start = px_timer_tick; uint32_t final = start + ms; // Waste CPU cycles like a slob - while (px_timer_tick != final); + while (px_timer_tick < final); // Return now that we've waited long enough return; } diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 31ebfe6f..9a419faf 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -18,7 +18,9 @@ // it seems to work fine for the specific intrinsic we need // we should probably investigate this further at some point... #define _X86INTRIN_H_INCLUDED +#define __X86INTRIN_H #include // needed for __rdtsc +#undef __X86INTRIN_H #undef _X86INTRIN_H_INCLUDED #include @@ -239,13 +241,11 @@ px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state s _px_stack_push_word(&stack_pointer, 0); _px_stack_push_word(&stack_pointer, 0); _px_stack_push_word(&stack_pointer, 0); - *new_task = { - .stack_top = (uintptr_t)stack_pointer, - .page_dir = px_get_phys_page_dir(), - .next_task = NULL, - .state = state, - .time_used = 0 - }; + new_task->stack_top = (uintptr_t)stack_pointer; + new_task->page_dir = px_get_phys_page_dir(); + new_task->next_task = NULL; + new_task->state = state; + new_task->time_used = 0; if (state == TASK_READY) { _px_tasks_enqueue_ready(new_task); } From b30db147f35a44cdfa47c98b4ba29c36014539d4 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 23 Oct 2020 22:10:10 -0400 Subject: [PATCH 063/139] Fixed missing volatile for px_timer_tick --- sysroot/usr/include/kernel/arch/i386/timer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysroot/usr/include/kernel/arch/i386/timer.hpp b/sysroot/usr/include/kernel/arch/i386/timer.hpp index 113277a1..6469b69b 100644 --- a/sysroot/usr/include/kernel/arch/i386/timer.hpp +++ b/sysroot/usr/include/kernel/arch/i386/timer.hpp @@ -17,7 +17,7 @@ #define TIMER_COMMAND_PORT 0x43 #define TIMER_DATA_PORT 0x40 -extern uint32_t px_timer_tick; +extern volatile uint32_t px_timer_tick; /** * @brief Initialize the CPU timer with the given frequency. From 7b57a76e7a035e36c3551b57e4356dad5f2a8332 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 23 Oct 2020 22:32:46 -0400 Subject: [PATCH 064/139] Fixes compilation issues on macOS --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 13c528f7..ee3c16c5 100755 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ CPP_FLAGS = \ # Assembler flags AS_FLAGS = --32 # Linker flags -LD_FLAGS = -T kernel/arch/i386/linker.ld -nostartfiles -nodefaultlibs -static-libgcc -lgcc +LD_FLAGS = --script kernel/arch/i386/linker.ld -L. -lgcc # *********************************** @@ -116,7 +116,7 @@ obj/%.o: kernel/%.S # Kernel object dist/kernel: $(OBJ) @ mkdir -p dist - $(CXX) -o $@ $(OBJ) $(CXXFLAGS) $(LD_FLAGS) + $(LD) -o $@ $(OBJ) $(LD_FLAGS) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym # Debug build From 8556dc44f376ec4eab262f3b1e0b031fb5a8ffb5 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 27 Oct 2020 23:50:19 -0400 Subject: [PATCH 065/139] Makefile now appends environment variables --- Makefile | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index ee3c16c5..35ea47c7 100755 --- a/Makefile +++ b/Makefile @@ -48,8 +48,9 @@ LD = $(shell command -v ld.lld) OBJCP = $(shell command -v llvm-objcopy) MKGRUB = $(shell command -v grub-mkrescue) # C / C++ flags (include directory) -CFLAGS = \ - -I ${SYSROOT}/usr/include/kernel/ +CFLAGS := \ + -I ${SYSROOT}/usr/include/kernel/ \ + ${CFLAGS} # C++ only flags (-lgcc flag is used b/c it has helpful functions) # Flags explained: # @@ -57,7 +58,7 @@ CFLAGS = \ # We need to ignore unused functions because we may use # them at a later time. For example, paging disable. # -CXXFLAGS = \ +CXXFLAGS := \ -m32 \ -target i386-none-elf \ -ffreestanding \ @@ -73,14 +74,16 @@ CXXFLAGS = \ -Wall \ -Werror \ -Wno-unused-function \ - -std=c++17 + -std=c++17 \ + ${CXXFLAGS} # C / C++ pre-processor flags -CPP_FLAGS = \ - -D VERSION=\"$(GIT_VERSION)\" +CPP_FLAGS := \ + -D VERSION=\"$(GIT_VERSION)\" \ + ${CPP_FLAGS} # Assembler flags -AS_FLAGS = --32 +AS_FLAGS := ${AS_FLAGS} --32 # Linker flags -LD_FLAGS = --script kernel/arch/i386/linker.ld -L. -lgcc +LD_FLAGS := ${LD_FLAGS} --script kernel/arch/i386/linker.ld -lgcc # *********************************** From 838546b526ecb9fa327525e3e28cc44660524e3a Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 28 Oct 2020 19:04:11 -0400 Subject: [PATCH 066/139] Updated makefile variable names --- Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 35ea47c7..eae4fe69 100755 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ MKGRUB = $(shell command -v grub-mkrescue) # C / C++ flags (include directory) CFLAGS := \ -I ${SYSROOT}/usr/include/kernel/ \ - ${CFLAGS} + ${PANIX_CFLAGS} # C++ only flags (-lgcc flag is used b/c it has helpful functions) # Flags explained: # @@ -58,7 +58,7 @@ CFLAGS := \ # We need to ignore unused functions because we may use # them at a later time. For example, paging disable. # -CXXFLAGS := \ +CXXFLAGS := \ -m32 \ -target i386-none-elf \ -ffreestanding \ @@ -75,15 +75,15 @@ CXXFLAGS := \ -Werror \ -Wno-unused-function \ -std=c++17 \ - ${CXXFLAGS} + ${PANIX_CXXFLAGS} # C / C++ pre-processor flags -CPP_FLAGS := \ +CPPFLAGS := \ -D VERSION=\"$(GIT_VERSION)\" \ - ${CPP_FLAGS} + ${PANIX_CPPFLAGS} # Assembler flags -AS_FLAGS := ${AS_FLAGS} --32 +ASFLAGS := ${PANIX_ASFLAGS} --32 # Linker flags -LD_FLAGS := ${LD_FLAGS} --script kernel/arch/i386/linker.ld -lgcc +LDFLAGS := ${PANIX_LDFLAGS} --script kernel/arch/i386/linker.ld -lgcc # *********************************** @@ -105,12 +105,12 @@ mkdir_obj_dirs: # C++ source -> object obj/%.o: kernel/%.cpp $(HEADERS) $(MAKE) mkdir_obj_dirs - $(CXX) $(CPP_FLAGS) $(CFLAGS) $(CXXFLAGS) -c -o $@ $< + $(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -c -o $@ $< # Assembly source -> object obj/%.o: kernel/%.s $(MAKE) mkdir_obj_dirs - $(AS) $(AS_FLAGS) -o $@ $< + $(AS) $(ASFLAGS) -o $@ $< obj/%.o: kernel/%.S $(MAKE) mkdir_obj_dirs @@ -119,7 +119,7 @@ obj/%.o: kernel/%.S # Kernel object dist/kernel: $(OBJ) @ mkdir -p dist - $(LD) -o $@ $(OBJ) $(LD_FLAGS) + $(LD) -o $@ $(OBJ) $(LDFLAGS) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym # Debug build From 71b1a96eb68e01e0194d5ee3cb9a260a76de5672 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Fri, 27 Nov 2020 18:10:25 -0500 Subject: [PATCH 067/139] Updated Makefile permissions --- Makefile | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Makefile diff --git a/Makefile b/Makefile old mode 100755 new mode 100644 From 39ae30c534e14ac27519961c4cef9b3235bead14 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Fri, 27 Nov 2020 20:59:48 -0500 Subject: [PATCH 068/139] Reverted back to GCC for compiler It makes things simpler --- Makefile | 39 +++++++++++++++++++++----------------- kernel/main.cpp | 2 -- kernel/sys/early_panic.cpp | 1 - 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index eae4fe69..5391ba2c 100644 --- a/Makefile +++ b/Makefile @@ -41,16 +41,16 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # ********************************** # Compilers/Assemblers/Linkers -AS = $(shell command -v i686-elf-as) NASM = $(shell command -v nasm) -CXX = $(shell command -v clang++) -LD = $(shell command -v ld.lld) -OBJCP = $(shell command -v llvm-objcopy) +AS = $(shell command -v i686-elf-as) +CXX = $(shell command -v i686-elf-gcc) +LD = $(shell command -v i686-elf-ld) +OBJCP = $(shell command -v i686-elf-objcopy) MKGRUB = $(shell command -v grub-mkrescue) # C / C++ flags (include directory) -CFLAGS := \ +CFLAGS := \ + ${PANIX_CFLAGS} \ -I ${SYSROOT}/usr/include/kernel/ \ - ${PANIX_CFLAGS} # C++ only flags (-lgcc flag is used b/c it has helpful functions) # Flags explained: # @@ -59,8 +59,8 @@ CFLAGS := \ # them at a later time. For example, paging disable. # CXXFLAGS := \ + ${PANIX_CXXFLAGS} \ -m32 \ - -target i386-none-elf \ -ffreestanding \ -fstack-protector-all \ -fpermissive \ @@ -74,16 +74,21 @@ CXXFLAGS := \ -Wall \ -Werror \ -Wno-unused-function \ - -std=c++17 \ - ${PANIX_CXXFLAGS} + -std=c++17 # C / C++ pre-processor flags -CPPFLAGS := \ +CPPFLAGS := \ + ${PANIX_CPPFLAGS} \ -D VERSION=\"$(GIT_VERSION)\" \ - ${PANIX_CPPFLAGS} # Assembler flags -ASFLAGS := ${PANIX_ASFLAGS} --32 +ASFLAGS := \ + ${PANIX_ASFLAGS} \ + --32 # Linker flags -LDFLAGS := ${PANIX_LDFLAGS} --script kernel/arch/i386/linker.ld -lgcc +LDFLAGS := \ + ${PANIX_LDFLAGS} \ + -m elf_i386 \ + -T kernel/arch/i386/linker.ld \ + -lgcc # *********************************** @@ -92,7 +97,7 @@ LDFLAGS := ${PANIX_LDFLAGS} --script kernel/arch/i386/linker.ld -lgcc # All objects OBJ = $(patsubst kernel/%.cpp, obj/%.o, $(CPP_SRC)) \ - $(patsubst kernel/%.s, obj/%.o, $(ATT_SRC)) \ + $(patsubst kernel/%.s, obj/%.o, $(ATT_SRC)) \ $(patsubst kernel/%.S, obj/%.o, $(NASM_SRC)) # Object directories, mirroring source OBJ_DIRS = $(subst kernel, obj, $(shell find kernel -type d)) @@ -188,9 +193,9 @@ vbox: vbox-create .PHONY: debugger debugger: dist/kernel # Start QEMU with debugger - ($(QEMU) \ - -S -s \ - -kernel $< \ + ($(QEMU) \ + -S -s \ + -kernel $< \ $(QEMU_FLAGS) > /dev/null &) sleep 1 wmctrl -xr qemu.Qemu-system-$(QEMU_ARCH) -b add,above diff --git a/kernel/main.cpp b/kernel/main.cpp index 37d6da05..623eb4b3 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -73,9 +73,7 @@ extern "C" void px_call_constructors() { * for when a smashed stack is detected. * */ -__attribute__ ((used)) uintptr_t __stack_chk_guard = STACK_CHK_GUARD; -__attribute__ ((used)) extern "C" void __stack_chk_fail(void) { PANIC("Smashed stack detected."); diff --git a/kernel/sys/early_panic.cpp b/kernel/sys/early_panic.cpp index b94780a0..be1cd679 100644 --- a/kernel/sys/early_panic.cpp +++ b/kernel/sys/early_panic.cpp @@ -14,7 +14,6 @@ extern "C" void __attribute__ ((section(".early_text"))) -__attribute__ ((optnone)) early_panic(const char *str) { volatile uint16_t* where; int x = 0; From da0af1ff4138027172e308cc86c6cfab872d96ac Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 11:24:57 -0500 Subject: [PATCH 069/139] Makefile now compiles C source properly --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 5391ba2c..5d8dc46a 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include ATT_SRC = $(shell find kernel -name "*.s") NASM_SRC = $(shell find kernel -name "*.S") +C_SRC = $(shell find kernel -name "*.c") CPP_SRC = $(shell find kernel -name "*.cpp") HEADERS = $(shell find $(INCLUDE) -name "*.hpp" -name "*.h") @@ -97,6 +98,7 @@ LDFLAGS := \ # All objects OBJ = $(patsubst kernel/%.cpp, obj/%.o, $(CPP_SRC)) \ + $(patsubst kernel/%.c, obj/%.o, $(C_SRC)) \ $(patsubst kernel/%.s, obj/%.o, $(ATT_SRC)) \ $(patsubst kernel/%.S, obj/%.o, $(NASM_SRC)) # Object directories, mirroring source @@ -107,6 +109,11 @@ OBJ_DIRS = $(subst kernel, obj, $(shell find kernel -type d)) mkdir_obj_dirs: mkdir -p $(OBJ_DIRS) +# C source -> object +obj/%.o: kernel/%.c $(HEADERS) + $(MAKE) mkdir_obj_dirs + $(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< + # C++ source -> object obj/%.o: kernel/%.cpp $(HEADERS) $(MAKE) mkdir_obj_dirs From b3f50ea7ff2e9675fc8dd040a59f0b6ab0d501eb Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 15:36:06 -0500 Subject: [PATCH 070/139] Added warnings section to makefile --- Makefile | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 5d8dc46a..b8ce6778 100644 --- a/Makefile +++ b/Makefile @@ -48,17 +48,35 @@ CXX = $(shell command -v i686-elf-gcc) LD = $(shell command -v i686-elf-ld) OBJCP = $(shell command -v i686-elf-objcopy) MKGRUB = $(shell command -v grub-mkrescue) -# C / C++ flags (include directory) +# Warning flags +# (Disable unused functions warning) +WARNINGS := \ + -Wno-unused-function \ + -Wall \ + -Wextra \ + -Winline \ + -Wshadow \ + -Wcast-align \ + -Wno-long-long \ + -Wpointer-arith \ + -Wconversion \ + -Wwrite-strings \ + -Wredundant-decls \ + -Wmissing-declarations +# TODO: Include -Werror once we +# Fix all of the warnings +# C only warnings +WARNINGS_C := \ + -Wnested-externs \ + -Wstrict-prototypes \ + -Wmissing-prototypes \ +# C & C++ flags (include directory) CFLAGS := \ ${PANIX_CFLAGS} \ + ${WARNINGS} \ -I ${SYSROOT}/usr/include/kernel/ \ -# C++ only flags (-lgcc flag is used b/c it has helpful functions) +# C++ flags # Flags explained: -# -# -Wno-unused-function -# We need to ignore unused functions because we may use -# them at a later time. For example, paging disable. -# CXXFLAGS := \ ${PANIX_CXXFLAGS} \ -m32 \ @@ -72,9 +90,6 @@ CXXFLAGS := \ -fno-rtti \ -fno-exceptions \ -fno-omit-frame-pointer \ - -Wall \ - -Werror \ - -Wno-unused-function \ -std=c++17 # C / C++ pre-processor flags CPPFLAGS := \ @@ -112,7 +127,7 @@ mkdir_obj_dirs: # C source -> object obj/%.o: kernel/%.c $(HEADERS) $(MAKE) mkdir_obj_dirs - $(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< + $(CXX) $(CFLAGS) $(CPPFLAGS) $(WARNINGS_C) -c -o $@ $< # C++ source -> object obj/%.o: kernel/%.cpp $(HEADERS) From c54135575294db735a5229ce78424ff161820728 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 15:36:46 -0500 Subject: [PATCH 071/139] Fixes for some of the warnings These ones were easier to fix. Dont think anything is broken b/c of this --- kernel/arch/arch.cpp | 7 +++++-- kernel/arch/i386/gdt.cpp | 2 ++ kernel/arch/i386/timer.cpp | 1 + kernel/lib/printf.cpp | 4 ++++ kernel/sys/early_panic.cpp | 4 ++++ kernel/sys/panic.cpp | 4 ++-- kernel/sys/tasks.cpp | 11 ++++++++--- sysroot/usr/include/kernel/arch/arch.hpp | 4 ++-- 8 files changed, 28 insertions(+), 9 deletions(-) diff --git a/kernel/arch/arch.cpp b/kernel/arch/arch.cpp index 55cee2ba..8ebec5b0 100644 --- a/kernel/arch/arch.cpp +++ b/kernel/arch/arch.cpp @@ -11,6 +11,9 @@ #include #include +// Function declarations +void px_kernel_print_multiboot_memmap(const multiboot_info_t* mb_struct); + const char* px_exception_descriptions[] = { "Divide-By-Zero", "Debugging", "Non-Maskable", "Breakpoint", "Overflow", "Out Bound Range", "Invalid Opcode", "Device Not Avbl", @@ -46,13 +49,13 @@ static inline int px_arch_cpuid_vendor(int flag, int regs[4]) { return (int)regs[0]; } -const char* const px_cpu_get_vendor() { +const char* px_cpu_get_vendor() { static char vendor[16]; px_arch_cpuid_vendor(0, (int *)(vendor)); return vendor; } -const char* const px_cpu_get_model() { +const char* px_cpu_get_model() { // The CPU model is broken up across 3 different calls, each using // EAX, EBX, ECX, and EDX to store the string, so we basically // are appending all 4 register values to this char array each time. diff --git a/kernel/arch/i386/gdt.cpp b/kernel/arch/i386/gdt.cpp index 9889ef6d..b2ca2b0d 100644 --- a/kernel/arch/i386/gdt.cpp +++ b/kernel/arch/i386/gdt.cpp @@ -17,6 +17,8 @@ // Defined in the gdt_flush.s file. extern "C" void gdt_flush(uintptr_t); +// Function declarations +void px_gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint16_t flags); // Define our local variables gdt_entry_t gdt_entries[5]; gdt_ptr_t gdt_ptr; diff --git a/kernel/arch/i386/timer.cpp b/kernel/arch/i386/timer.cpp index 9be8e3c8..09909bd8 100644 --- a/kernel/arch/i386/timer.cpp +++ b/kernel/arch/i386/timer.cpp @@ -47,6 +47,7 @@ void px_timer_init(uint32_t freq) { } static void px_timer_callback(registers_t *regs) { + (void)regs; px_timer_tick++; for (size_t i = 0; i < _callback_count; i++) { _callbacks[i](); diff --git a/kernel/lib/printf.cpp b/kernel/lib/printf.cpp index 73939ce4..386b0868 100644 --- a/kernel/lib/printf.cpp +++ b/kernel/lib/printf.cpp @@ -92,6 +92,10 @@ Using & for division here, so STACK_WIDTH must be a power of 2. */ #define PR_BUFLEN 16 typedef int (*fnptr_t)(unsigned c, void** helper); + +/* Function declarations */ +int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr); + /***************************************************************************** name: do_printf action: minimal subfunction for ?printf, calls function diff --git a/kernel/sys/early_panic.cpp b/kernel/sys/early_panic.cpp index be1cd679..6d6b1285 100644 --- a/kernel/sys/early_panic.cpp +++ b/kernel/sys/early_panic.cpp @@ -12,6 +12,10 @@ #include #include +// Provide a function prototype to make the compiler warnings happy. Don't +// want to make it public though, so we won't put it in the panic header. +extern "C" void early_panic(const char *str); + extern "C" void __attribute__ ((section(".early_text"))) early_panic(const char *str) { diff --git a/kernel/sys/panic.cpp b/kernel/sys/panic.cpp index cb2d845f..513246a8 100644 --- a/kernel/sys/panic.cpp +++ b/kernel/sys/panic.cpp @@ -18,6 +18,7 @@ #include // Function prototypes +void printPanicScreen(int exception); void panic_print_file(const char *file, uint32_t line, const char *func); void panic_print_register(registers_t *regs); @@ -68,7 +69,7 @@ void panic(registers_t *regs, const char *file, uint32_t line, const char *func) asm volatile ("cli"); // Print the panic cow and exception description printPanicScreen(regs->int_num); - char msg[64]; + char msg[128]; px_ksprintf( msg, "Exception: %i (%s)\n\n", @@ -109,7 +110,6 @@ void panic(registers_t *regs, const char *file, uint32_t line, const char *func) const char* uss = (us ? "user-mode " : "kernel "); const char* avail = (reserved ? "reserved" : "available"); // Now that we assigned all of our string, put together the message - char msg[128]; px_ksprintf( msg, "Page fault (%s%s%s%s) at 0x0x%08X (id -> %i)\n", diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 9a419faf..ff0533bd 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -29,10 +29,13 @@ static void _enqueue_task(px_tasklist_t *, px_task *); static px_task_t *_dequeue_task(px_tasklist_t *); static void _cleaner_task_impl(void); +extern "C" void _px_tasks_enqueue_ready(px_task_t *task); +void px_tasks_update_time(); +void _wakeup(px_task_t *task); /* macro to create a new named tasklist and associated helper functions */ #define NAMED_TASKLIST(name) \ - px_tasklist_t px_tasks_##name = { 0 }; \ + px_tasklist_t px_tasks_##name = { 0, 0 }; \ static inline void _enqueue_##name(px_task_t *task) { \ _enqueue_task(&px_tasks_##name, task); } \ static inline px_task_t *_dequeue_##name() { \ @@ -42,7 +45,7 @@ px_task_t *px_current_task = NULL; static px_task_t _cleaner_task; static px_task_t _first_task; -px_tasklist_t px_tasks_ready = { 0 }; +px_tasklist_t px_tasks_ready = { 0, 0 }; NAMED_TASKLIST(sleeping); NAMED_TASKLIST(stopped); @@ -102,7 +105,9 @@ void px_tasks_init() // this task is currently running .state = TASK_RUNNING, // just say that this task hasn't spent any time running yet - .time_used = 0 + .time_used = 0, + // Set wakeup time to 0 to make compiler happy + .wakeup_time = 0 }; // create a task for the cleaner and set it's state to "paused" (void) px_tasks_new(_cleaner_task_impl, &_cleaner_task, TASK_PAUSED); diff --git a/sysroot/usr/include/kernel/arch/arch.hpp b/sysroot/usr/include/kernel/arch/arch.hpp index ecc7e05e..de0c94ee 100644 --- a/sysroot/usr/include/kernel/arch/arch.hpp +++ b/sysroot/usr/include/kernel/arch/arch.hpp @@ -15,8 +15,8 @@ #ifndef PANIX_ARCH_HPP #define PANIX_ARCH_HPP -const char* const px_cpu_get_vendor(); -const char* const px_cpu_get_model(); +const char* px_cpu_get_vendor(); +const char* px_cpu_get_model(); struct registers; typedef struct registers registers_t; From 7fa02d724747e829b9776594cb148524d080761a Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 16:10:55 -0500 Subject: [PATCH 072/139] Divided C & C++ flags --- Makefile | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index b8ce6778..e07401f4 100644 --- a/Makefile +++ b/Makefile @@ -66,19 +66,12 @@ WARNINGS := \ # TODO: Include -Werror once we # Fix all of the warnings # C only warnings -WARNINGS_C := \ +CWARNINGS := \ -Wnested-externs \ -Wstrict-prototypes \ -Wmissing-prototypes \ -# C & C++ flags (include directory) -CFLAGS := \ - ${PANIX_CFLAGS} \ - ${WARNINGS} \ - -I ${SYSROOT}/usr/include/kernel/ \ -# C++ flags -# Flags explained: -CXXFLAGS := \ - ${PANIX_CXXFLAGS} \ +# Common (C & C++) flags +FLAGS := \ -m32 \ -ffreestanding \ -fstack-protector-all \ @@ -90,11 +83,24 @@ CXXFLAGS := \ -fno-rtti \ -fno-exceptions \ -fno-omit-frame-pointer \ +# C flags (include directory) +CFLAGS := \ + ${FLAGS} \ + ${PANIX_CFLAGS} \ + ${WARNINGS} \ + $(CWARNINGS) \ + -std=c17 +# C++ flags +CXXFLAGS := \ + ${FLAGS} \ + ${PANIX_CXXFLAGS} \ + ${WARNINGS} \ -std=c++17 # C / C++ pre-processor flags CPPFLAGS := \ ${PANIX_CPPFLAGS} \ -D VERSION=\"$(GIT_VERSION)\" \ + -I ${SYSROOT}/usr/include/kernel/ # Assembler flags ASFLAGS := \ ${PANIX_ASFLAGS} \ @@ -106,7 +112,6 @@ LDFLAGS := \ -T kernel/arch/i386/linker.ld \ -lgcc - # *********************************** # * Source Code Compilation Targets * # *********************************** @@ -127,12 +132,12 @@ mkdir_obj_dirs: # C source -> object obj/%.o: kernel/%.c $(HEADERS) $(MAKE) mkdir_obj_dirs - $(CXX) $(CFLAGS) $(CPPFLAGS) $(WARNINGS_C) -c -o $@ $< + $(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< # C++ source -> object obj/%.o: kernel/%.cpp $(HEADERS) $(MAKE) mkdir_obj_dirs - $(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -c -o $@ $< + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< # Assembly source -> object obj/%.o: kernel/%.s From 8b0fee1dd7f6d7013f41c99e43b79eccedf25819 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 16:11:48 -0500 Subject: [PATCH 073/139] Fixed a lot more warnings --- kernel/dev/kbd/kbd.cpp | 4 +++- kernel/dev/rtc/rtc.cpp | 5 +++++ kernel/dev/serial/rs232.cpp | 2 +- kernel/lib/printf.cpp | 11 +++++++++-- kernel/lib/semaphore.cpp | 3 +++ kernel/lib/string.cpp | 4 ++-- kernel/main.cpp | 5 +++++ kernel/mem/heap.cpp | 5 ++++- kernel/mem/paging.cpp | 17 +++++++++++++++-- kernel/sys/tasks.cpp | 4 ++-- 10 files changed, 49 insertions(+), 11 deletions(-) diff --git a/kernel/dev/kbd/kbd.cpp b/kernel/dev/kbd/kbd.cpp index de671d57..bb095968 100644 --- a/kernel/dev/kbd/kbd.cpp +++ b/kernel/dev/kbd/kbd.cpp @@ -19,6 +19,8 @@ uint8_t px_kbd_scode_buff_pos = 0; void px_kbd_push_scode(uint8_t scode); static void px_kbd_callback(registers_t *regs) { + // Ignore the registers for now + (void)regs; uint8_t scode = px_read_byte(KBD_DATA_PORT); // If the keyboard scancode corresponds to an "on key down" px_kbd_push_scode(scode); @@ -32,5 +34,5 @@ void px_kbd_push_scode(uint8_t scode) { // Push our scancode onto the buffer px_kbd_scode_buff[px_kbd_scode_buff_pos] = scode; // Increment and loop back if necessary - px_kbd_scode_buff_pos = (px_kbd_scode_buff_pos + 1) % 256; + px_kbd_scode_buff_pos = (uint8_t)((px_kbd_scode_buff_pos + 1) % 256); } \ No newline at end of file diff --git a/kernel/dev/rtc/rtc.cpp b/kernel/dev/rtc/rtc.cpp index 1fa6ca28..fb3bea52 100644 --- a/kernel/dev/rtc/rtc.cpp +++ b/kernel/dev/rtc/rtc.cpp @@ -16,6 +16,10 @@ #include void px_rtc_callback(registers_t *regs); +int px_rtc_get_update_in_progress(); +uint8_t px_rtc_get_register(int reg); +void px_read_rtc(); + // Current values from RTC uint8_t px_rtc_second; // Current UTC second uint8_t px_rtc_minute; // Current UTC minute @@ -40,6 +44,7 @@ void px_rtc_init() { } void px_rtc_callback(registers_t *regs) { + (void)regs; px_kprintf(DBG_INFO "RTC updated.\n"); } diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 805036d7..f1142b30 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -25,7 +25,6 @@ static int px_rs232_is_transmit_empty(); static char px_rs232_read_char(); static void px_rs232_write_char(char c); static void px_rs232_callback(registers_t *regs); -void px_rs232_init(uint16_t port_num); static int px_rs232_received() { return px_read_byte(rs_232_port_base + RS_232_LINE_STATUS_REG) & 1; @@ -52,6 +51,7 @@ void px_rs232_print(const char* str) { } static void px_rs232_callback(registers_t *regs) { + (void)regs; // Grab the input character char in = px_rs232_read_char(); // Change carriage returns to newlines diff --git a/kernel/lib/printf.cpp b/kernel/lib/printf.cpp index 386b0868..c677e9e6 100644 --- a/kernel/lib/printf.cpp +++ b/kernel/lib/printf.cpp @@ -95,6 +95,7 @@ typedef int (*fnptr_t)(unsigned c, void** helper); /* Function declarations */ int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr); +int vprintf_help(unsigned c, void** ptr); /***************************************************************************** name: do_printf @@ -178,6 +179,7 @@ int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr) /* FALL THROUGH */ /* STATE 4: AWAITING CONVERSION CHARS (Xxpndiuocs) */ case 4: + { where = buf + PR_BUFLEN - 1; *where = '\0'; switch (*fmt) { @@ -225,7 +227,7 @@ int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr) } } /* convert binary to octal/decimal/hex ASCII -OK, I found my mistake. The math here is _always_ unsigned */ + OK, I found my mistake. The math here is _always_ unsigned */ do { unsigned long temp; @@ -292,6 +294,10 @@ OK, I found my mistake. The math here is _always_ unsigned */ default: break; } + // Tell the compiler that this isn't an issue + // (at least I'm assuming it isn't) + [[fallthrough]]; + } default: state = flags = given_wd = 0; break; @@ -337,7 +343,8 @@ int px_ksprintf(char* buf, const char* fmt, ...) *****************************************************************************/ int vprintf_help(unsigned c, void** ptr) { - putchar(c); + (void)ptr; + putchar((char)c); return 0; } /***************************************************************************** diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index a54503a8..4c52dd9a 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -97,6 +97,7 @@ int sem_trywait(px_sem_t *sem) { int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { // TODO: Add the timer functionality here. + (void)usec; // Check if the semaphore is valid if (sem == NULL) { @@ -131,6 +132,8 @@ int px_sem_post(px_sem_t *sem) { } uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val) { + // FIXME: I don't think val should be unused? + (void)val; // Check if the semaphore is valid if (sem == NULL) { diff --git a/kernel/lib/string.cpp b/kernel/lib/string.cpp index 9dff0d10..cd93c152 100644 --- a/kernel/lib/string.cpp +++ b/kernel/lib/string.cpp @@ -46,7 +46,7 @@ void reverse(char* s) { for (int i = 0; i < j; i++, j--) { c = s[i]; s[i] = s[j]; - s[j] = c; + s[j] = (char)c; } } @@ -55,7 +55,7 @@ void itoa(int n, char str[]) { if ((sign = n) < 0) n = -n; i = 0; do { - str[i++] = n % 10 + '0'; + str[i++] = (char)(n % 10 + (int)'0'); } while ((n /= 10) > 0); if (sign < 0) str[i++] = '-'; diff --git a/kernel/main.cpp b/kernel/main.cpp index 623eb4b3..01bb79f0 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -36,6 +36,9 @@ #define VERSION "unknown" #endif +extern "C" void px_call_constructors(); +extern "C" void __stack_chk_fail(void); +extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_magic); void px_kernel_print_splash(); void px_kernel_boot_tone(); @@ -84,6 +87,8 @@ extern "C" void __stack_chk_fail(void) * assembly written in boot.S located in arch/i386/boot.S. */ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_magic) { + (void)mb_struct; + (void)mb_magic; // Print the splash screen to show we've booted into the kernel properly. px_kernel_print_splash(); // Install the GDT diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp index fd1f7b9c..b5078096 100644 --- a/kernel/mem/heap.cpp +++ b/kernel/mem/heap.cpp @@ -36,6 +36,9 @@ px_heap_chunk_t* last = NULL; void* slot[NUM_SLOTS] = { NULL }; +// Function declarations +void check(void); + static void px_memory_chunk_init(px_heap_chunk_t* chunk) { px_debugf("%s(0x%p)\n", __FUNCTION__, chunk); dlist_init(&chunk->all); @@ -155,7 +158,7 @@ void* malloc(size_t size) { px_memory_chunk_init(chunk2); dlist_insert_after(&chunk->all, &chunk2->all); len = px_memory_chunk_size(chunk2); - int n = px_memory_chunk_slot(len); + n = px_memory_chunk_slot(len); px_debugf(" adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); DLIST_PUSH(&free_chunk[n], chunk2, free); mem_meta += HEADER_SIZE; diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 3a9e68cb..1ede2993 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -73,6 +73,12 @@ static inline void px_map_kernel_page_table(uint32_t pd_idx, px_page_table_t *ta .present = 1, .read_write = 1, .usermode = 0, + .write_through = 0, + .cache_disable = 0, + .accessed = 0, + .ignored_a = 0, + .page_size = 0, + .ignored_b = 0, // compute the physical address of this page table // the virtual address is obtained with the & operator and // the offset is applied from the load address of the kernel @@ -88,7 +94,7 @@ static void px_paging_init_dir() { px_map_kernel_page_table(i, &page_tables[i]); // clear out the page tables for (int j = 0; j < PAGE_ENTRIES; j++) { - page_tables[i].pages[j] = (px_page_table_entry_t){ 0 }; + page_tables[i].pages[j] = (px_page_table_entry_t){ /* ZERO */ }; } } // recursively map the last page table to the page directory @@ -132,6 +138,13 @@ static void px_map_kernel_page(px_virtual_address_t vaddr, uint32_t paddr) { .present = 1, // The page is present .read_write = 1, // The page has r/w permissions .usermode = 0, // These are kernel pages + .write_through = 0, // Disable write through + .cache_disable = 0, // The page is cached + .accessed = 0, // The page is unaccessed + .dirty = 0, // The page is clean + .page_att_table = 0, // The page has no attribute table + .global = 0, // The page is local + .unused = 0, // Ignored .frame = paddr >> 12 // The last 20 bits are the frame }; // Set the associated bit in the bitmaps @@ -224,7 +237,7 @@ void px_free_page(void *page, uint32_t size) { // basically it's frame 0, 1...(2^21-1) bitmap_clear_bit(mapped_mem, pte->frame); // zero it out to unmap it - *pte = { 0 }; + *pte = { /* Zero */ }; // clear that tlb px_invalidate_page(page); } diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index ff0533bd..53c22ad9 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -35,7 +35,7 @@ void _wakeup(px_task_t *task); /* macro to create a new named tasklist and associated helper functions */ #define NAMED_TASKLIST(name) \ - px_tasklist_t px_tasks_##name = { 0, 0 }; \ + px_tasklist_t px_tasks_##name = { /* Zero */ }; \ static inline void _enqueue_##name(px_task_t *task) { \ _enqueue_task(&px_tasks_##name, task); } \ static inline px_task_t *_dequeue_##name() { \ @@ -45,7 +45,7 @@ px_task_t *px_current_task = NULL; static px_task_t _cleaner_task; static px_task_t _first_task; -px_tasklist_t px_tasks_ready = { 0, 0 }; +px_tasklist_t px_tasks_ready = { /* Zero */ }; NAMED_TASKLIST(sleeping); NAMED_TASKLIST(stopped); From ad7078c08f724fd87e1d07c705f90cda7d835eed Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 16:30:32 -0500 Subject: [PATCH 074/139] Fixed tabs / spaces issue --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e07401f4..81e41561 100644 --- a/Makefile +++ b/Makefile @@ -59,9 +59,9 @@ WARNINGS := \ -Wcast-align \ -Wno-long-long \ -Wpointer-arith \ - -Wconversion \ - -Wwrite-strings \ - -Wredundant-decls \ + -Wconversion \ + -Wwrite-strings \ + -Wredundant-decls \ -Wmissing-declarations # TODO: Include -Werror once we # Fix all of the warnings From bacb5f90f07af35947b7c5b7f77590fcab87880a Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 17:11:28 -0500 Subject: [PATCH 075/139] Directories are variables, C -> gcc, C++ -> g++ --- Makefile | 131 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/Makefile b/Makefile index 81e41561..a3d5ada5 100644 --- a/Makefile +++ b/Makefile @@ -8,46 +8,41 @@ GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" # ***************************** -# * Various Source Code Flags * +# * Source Code & Directories * # ***************************** +# Directories +BUILD = obj +LIBRARY = libs +KERNEL = kernel +PRODUCT = dist SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include -ATT_SRC = $(shell find kernel -name "*.s") -NASM_SRC = $(shell find kernel -name "*.S") -C_SRC = $(shell find kernel -name "*.c") -CPP_SRC = $(shell find kernel -name "*.cpp") -HEADERS = $(shell find $(INCLUDE) -name "*.hpp" -name "*.h") -# ********************************* -# * Various Virtual Machine Flags * -# ********************************* +# Source code +ATT_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.s") +NASM_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.S") +C_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.c") +CPP_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.cpp") +HEADERS = $(shell find $(INCLUDE) $(LIBRARY) -name "*.hpp" -or -name "*.h") -# QEMU flags -QEMU_FLAGS = \ - -m 4G \ - -rtc clock=host \ - -vga std \ - -serial stdio -QEMU_ARCH = i386 -# Virtualbox flags -VM_NAME = panix-box -VBOX_VM_FILE=dist/$(VM_NAME)/$(VM_NAME).vbox -# VM executable locations -VBOX = $(shell command -v VBoxManage) -QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) - -# ********************************** -# * 32-Bit i686 Architecture Flags * -# ********************************** +# ******************* +# * i686 Toolchains * +# ******************* # Compilers/Assemblers/Linkers NASM = $(shell command -v nasm) AS = $(shell command -v i686-elf-as) -CXX = $(shell command -v i686-elf-gcc) +CC = $(shell command -v i686-elf-gcc) +CXX = $(shell command -v i686-elf-g++) LD = $(shell command -v i686-elf-ld) OBJCP = $(shell command -v i686-elf-objcopy) MKGRUB = $(shell command -v grub-mkrescue) + +# ******************* +# * Toolchain Flags * +# ******************* + # Warning flags # (Disable unused functions warning) WARNINGS := \ @@ -112,17 +107,31 @@ LDFLAGS := \ -T kernel/arch/i386/linker.ld \ -lgcc -# *********************************** -# * Source Code Compilation Targets * -# *********************************** +# ************************ +# * Kernel Build Targets * +# ************************ + +# Debug build +debug: CXXFLAGS += -DDEBUG -g +debug: CFLAGS += -DDEBUG -g +debug: dist/kernel + +# Release build +release: CXXFLAGS += -O3 -mno-avx +release: CFLAGS += -O3 -mno-avx +release: dist/kernel + +# ************************* +# * Kernel Source Objects * +# ************************* # All objects -OBJ = $(patsubst kernel/%.cpp, obj/%.o, $(CPP_SRC)) \ - $(patsubst kernel/%.c, obj/%.o, $(C_SRC)) \ - $(patsubst kernel/%.s, obj/%.o, $(ATT_SRC)) \ - $(patsubst kernel/%.S, obj/%.o, $(NASM_SRC)) +OBJ = $(patsubst $(KERNEL)/%.cpp, $(BUILD)/%.o, $(CPP_SRC)) \ + $(patsubst $(KERNEL)/%.c, $(BUILD)/%.o, $(C_SRC)) \ + $(patsubst $(KERNEL)/%.s, $(BUILD)/%.o, $(ATT_SRC)) \ + $(patsubst $(KERNEL)/%.S, $(BUILD)/%.o, $(NASM_SRC)) # Object directories, mirroring source -OBJ_DIRS = $(subst kernel, obj, $(shell find kernel -type d)) +OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) # Create object file directories .PHONY: mkdir_obj_dirs @@ -130,40 +139,28 @@ mkdir_obj_dirs: mkdir -p $(OBJ_DIRS) # C source -> object -obj/%.o: kernel/%.c $(HEADERS) +$(BUILD)/%.o: $(KERNEL)/%.c $(HEADERS) $(MAKE) mkdir_obj_dirs - $(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< - + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< # C++ source -> object -obj/%.o: kernel/%.cpp $(HEADERS) +$(BUILD)/%.o: $(KERNEL)/%.cpp $(HEADERS) $(MAKE) mkdir_obj_dirs $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< - -# Assembly source -> object -obj/%.o: kernel/%.s +# GAS assembly -> object +$(BUILD)/%.o: $(KERNEL)/%.s $(MAKE) mkdir_obj_dirs $(AS) $(ASFLAGS) -o $@ $< - -obj/%.o: kernel/%.S +# NASM assembly -> object +$(BUILD)/%.o: $(KERNEL)/%.S $(MAKE) mkdir_obj_dirs $(NASM) -f elf32 -o $@ $< # Kernel object -dist/kernel: $(OBJ) +$(PRODUCT)/kernel: $(OBJ) @ mkdir -p dist $(LD) -o $@ $(OBJ) $(LDFLAGS) $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym -# Debug build -debug: CXXFLAGS += -DDEBUG -g -debug: CFLAGS += -DDEBUG -g -debug: dist/kernel - -# Release build -release: CXXFLAGS += -O3 -mno-avx -release: CFLAGS += -O3 -mno-avx -release: dist/kernel - # ******************************** # * Kernel Distribution Creation * # ******************************** @@ -189,6 +186,24 @@ vmdk: dist/kernel @ qemu-img convert -f raw -O vmdk dist/kernel dist/panix.vmdk @ echo Done building VMDK image of Panix! +# ************************* +# * Virtual Machine Flags * +# ************************* + +# QEMU flags +QEMU_FLAGS = \ + -m 4G \ + -rtc clock=host \ + -vga std \ + -serial stdio +QEMU_ARCH = i386 +# Virtualbox flags +VM_NAME = panix-box +VBOX_VM_FILE=dist/$(VM_NAME)/$(VM_NAME).vbox +# VM executable locations +VBOX = $(shell command -v VBoxManage) +QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) + # *************************** # * Virtual Machine Testing * # *************************** @@ -229,9 +244,9 @@ debugger: dist/kernel # After this start the visual studio debugger # gdb dist/kernel -# ************************************ -# * Doxygen Documentation Generation * -# ************************************ +# **************************** +# * Documentation Generation * +# **************************** .PHONY: docs docs: From 2c7eb76ad896937bf587064239a624051918dc17 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 17:24:31 -0500 Subject: [PATCH 076/139] Disable optimization for early_panic --- kernel/sys/early_panic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sys/early_panic.cpp b/kernel/sys/early_panic.cpp index 6d6b1285..a9572da4 100644 --- a/kernel/sys/early_panic.cpp +++ b/kernel/sys/early_panic.cpp @@ -18,6 +18,7 @@ extern "C" void early_panic(const char *str); extern "C" void __attribute__ ((section(".early_text"))) +__attribute__((optimize("O0"))) early_panic(const char *str) { volatile uint16_t* where; int x = 0; From 2d199584b52cdf2da4af90b9f37b6f42728c8d8e Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 19:12:21 -0500 Subject: [PATCH 077/139] Reordered flags by category & length --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index a3d5ada5..819e547b 100644 --- a/Makefile +++ b/Makefile @@ -46,17 +46,17 @@ MKGRUB = $(shell command -v grub-mkrescue) # Warning flags # (Disable unused functions warning) WARNINGS := \ - -Wno-unused-function \ -Wall \ -Wextra \ -Winline \ -Wshadow \ + -Wconversion \ -Wcast-align \ -Wno-long-long \ -Wpointer-arith \ - -Wconversion \ -Wwrite-strings \ -Wredundant-decls \ + -Wno-unused-function \ -Wmissing-declarations # TODO: Include -Werror once we # Fix all of the warnings @@ -68,15 +68,15 @@ CWARNINGS := \ # Common (C & C++) flags FLAGS := \ -m32 \ - -ffreestanding \ - -fstack-protector-all \ - -fpermissive \ -nostdlib \ -nodefaultlibs \ - -fno-use-cxa-atexit \ - -fno-builtin \ + -fpermissive \ + -ffreestanding \ + -fstack-protector-all \ -fno-rtti \ + -fno-builtin \ -fno-exceptions \ + -fno-use-cxa-atexit \ -fno-omit-frame-pointer \ # C flags (include directory) CFLAGS := \ @@ -159,7 +159,7 @@ $(BUILD)/%.o: $(KERNEL)/%.S $(PRODUCT)/kernel: $(OBJ) @ mkdir -p dist $(LD) -o $@ $(OBJ) $(LDFLAGS) - $(OBJCP) --only-keep-debug dist/kernel dist/panix.sym + $(OBJCP) --only-keep-debug $(PRODUCT)/kernel $(PRODUCT)/panix.sym # ******************************** # * Kernel Distribution Creation * From eb3af5e70f2d62ba0d71348f9b2562b5e8b85ed0 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Sat, 28 Nov 2020 20:42:28 -0500 Subject: [PATCH 078/139] Updated ISO target with prereqs Also remove VMDK and VDI targets --- Makefile | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 819e547b..aff746d5 100644 --- a/Makefile +++ b/Makefile @@ -166,26 +166,13 @@ $(PRODUCT)/kernel: $(OBJ) # ******************************** # Create bootable ISO -.PHONY: iso -iso: dist/kernel +iso: $(PRODUCT)/kernel @ mkdir -p iso/boot/grub @ cp dist/kernel iso/boot/ @ cp boot/grub.cfg iso/boot/grub/grub.cfg - @ $(MKGRUB) -o dist/panix.iso iso + @ $(MKGRUB) -o $(PRODUCT)/panix.iso iso @ rm -rf iso -.PHONY: vdi -vdi: dist/kernel - @ echo Building VDI image of Panix... - @ qemu-img convert -f raw -O vdi dist/kernel dist/panix.vdi - @ echo Done building VDI image of Panix! - -.PHONY: vmdk -vmdk: dist/kernel - @ echo "\nBuilding VMDK image of Panix..." - @ qemu-img convert -f raw -O vmdk dist/kernel dist/panix.vmdk - @ echo Done building VMDK image of Panix! - # ************************* # * Virtual Machine Flags * # ************************* @@ -210,14 +197,14 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # Run Panix in QEMU .PHONY: run -run: dist/kernel +run: $(PRODUCT)/kernel $(QEMU) \ -kernel dist/kernel \ $(QEMU_FLAGS) # Create Virtualbox VM .PHONY: vbox-create -vbox-create: dist/panix.iso +vbox-create: $(PRODUCT)/panix.iso $(VBOX) createvm --register --name $(VM_NAME) --basefolder $(shell pwd)/dist $(VBOX) modifyvm $(VM_NAME) \ --memory 256 --ioapic on --cpus 2 --vram 16 \ @@ -233,7 +220,7 @@ vbox: vbox-create # Open the connection to qemu and load our kernel-object file with symbols .PHONY: debugger -debugger: dist/kernel +debugger: $(PRODUCT)/kernel # Start QEMU with debugger ($(QEMU) \ -S -s \ From 10a4ac2589ebb340f154dbd450ab30bf47f03fd6 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 21:33:20 -0500 Subject: [PATCH 079/139] Makefile output has been prettified --- Makefile | 72 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index aff746d5..38aca8eb 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,13 @@ .DEFAULT_GOAL := release GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" +# ****************************** +# * Compiler Output Formatting * +# ****************************** + +COLOR_COM = \033[0;34m +COLOR_NONE = \033[m + # ***************************** # * Source Code & Directories * # ***************************** @@ -47,10 +54,10 @@ MKGRUB = $(shell command -v grub-mkrescue) # (Disable unused functions warning) WARNINGS := \ -Wall \ + -Werror \ -Wextra \ -Winline \ -Wshadow \ - -Wconversion \ -Wcast-align \ -Wno-long-long \ -Wpointer-arith \ @@ -58,8 +65,8 @@ WARNINGS := \ -Wredundant-decls \ -Wno-unused-function \ -Wmissing-declarations -# TODO: Include -Werror once we -# Fix all of the warnings +# Flags to be added later +# -Wconversion # C only warnings CWARNINGS := \ -Wnested-externs \ @@ -77,7 +84,7 @@ FLAGS := \ -fno-builtin \ -fno-exceptions \ -fno-use-cxa-atexit \ - -fno-omit-frame-pointer \ + -fno-omit-frame-pointer # C flags (include directory) CFLAGS := \ ${FLAGS} \ @@ -136,30 +143,33 @@ OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) # Create object file directories .PHONY: mkdir_obj_dirs mkdir_obj_dirs: - mkdir -p $(OBJ_DIRS) + @mkdir -p $(OBJ_DIRS) # C source -> object $(BUILD)/%.o: $(KERNEL)/%.c $(HEADERS) - $(MAKE) mkdir_obj_dirs - $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + @$(MAKE) mkdir_obj_dirs + @$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + @printf "$(COLOR_COM)(CC)$(COLOR_NONE)\t$@\n" # C++ source -> object $(BUILD)/%.o: $(KERNEL)/%.cpp $(HEADERS) - $(MAKE) mkdir_obj_dirs - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + @$(MAKE) mkdir_obj_dirs + @$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + @printf "$(COLOR_COM)(CXX)$(COLOR_NONE)\t$@\n" # GAS assembly -> object $(BUILD)/%.o: $(KERNEL)/%.s - $(MAKE) mkdir_obj_dirs - $(AS) $(ASFLAGS) -o $@ $< + @$(MAKE) mkdir_obj_dirs + @$(AS) $(ASFLAGS) -o $@ $< + @printf "$(COLOR_COM)(AS)$(COLOR_NONE)\t$@\n" # NASM assembly -> object $(BUILD)/%.o: $(KERNEL)/%.S - $(MAKE) mkdir_obj_dirs - $(NASM) -f elf32 -o $@ $< - + @$(MAKE) mkdir_obj_dirs + @$(NASM) -f elf32 -o $@ $< + @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" # Kernel object $(PRODUCT)/kernel: $(OBJ) - @ mkdir -p dist - $(LD) -o $@ $(OBJ) $(LDFLAGS) - $(OBJCP) --only-keep-debug $(PRODUCT)/kernel $(PRODUCT)/panix.sym + @mkdir -p dist + @$(LD) -o $@ $(OBJ) $(LDFLAGS) + @$(OBJCP) --only-keep-debug $(PRODUCT)/kernel $(PRODUCT)/panix.sym # ******************************** # * Kernel Distribution Creation * @@ -167,11 +177,11 @@ $(PRODUCT)/kernel: $(OBJ) # Create bootable ISO iso: $(PRODUCT)/kernel - @ mkdir -p iso/boot/grub - @ cp dist/kernel iso/boot/ - @ cp boot/grub.cfg iso/boot/grub/grub.cfg - @ $(MKGRUB) -o $(PRODUCT)/panix.iso iso - @ rm -rf iso + @mkdir -p iso/boot/grub + @cp dist/kernel iso/boot/ + @cp boot/grub.cfg iso/boot/grub/grub.cfg + @$(MKGRUB) -o $(PRODUCT)/panix.iso iso + @rm -rf iso # ************************* # * Virtual Machine Flags * @@ -237,8 +247,8 @@ debugger: $(PRODUCT)/kernel .PHONY: docs docs: - @ echo Generating docs according to the Doxyfile... - @ doxygen ./Doxyfile + @echo Generating docs according to the Doxyfile... + @doxygen ./Doxyfile # ******************** # * Cleaning Targets * @@ -247,13 +257,13 @@ docs: # Clear out objects and BIN .PHONY: clean clean: - @ echo Cleaning obj directory... - @ rm -rf obj - @ echo Cleaning bin files... - @ rm -rf dist/* - @ echo "Done cleaning!" + @echo Cleaning obj directory... + @rm -rf obj + @echo Cleaning bin files... + @rm -rf dist/* + @echo "Done cleaning!" .PHONY: clean-vm clean-vm: - @ echo Removing VM - @ $(VBOX) unregistervm $(VM_NAME) --delete + @echo Removing VM + @$(VBOX) unregistervm $(VM_NAME) --delete From 0d7fe077c084306431231551f37eaa411b4e4ee4 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 21:46:04 -0500 Subject: [PATCH 080/139] Headers are now dependencies Cleaning also works better and few other changes --- Makefile | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 38aca8eb..ea325f50 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" # ****************************** COLOR_COM = \033[0;34m +COLOR_OK = \033[0;32m COLOR_NONE = \033[m # ***************************** @@ -22,6 +23,7 @@ COLOR_NONE = \033[m BUILD = obj LIBRARY = libs KERNEL = kernel +SYMBOLS = $(KERNEL).sym PRODUCT = dist SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include @@ -139,6 +141,10 @@ OBJ = $(patsubst $(KERNEL)/%.cpp, $(BUILD)/%.o, $(CPP_SRC)) \ $(patsubst $(KERNEL)/%.S, $(BUILD)/%.o, $(NASM_SRC)) # Object directories, mirroring source OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) +# Dependency files +DEP = $(OBJ:%.o=%.d) +# Include all .d files +-include $(DEP) # Create object file directories .PHONY: mkdir_obj_dirs @@ -148,12 +154,12 @@ mkdir_obj_dirs: # C source -> object $(BUILD)/%.o: $(KERNEL)/%.c $(HEADERS) @$(MAKE) mkdir_obj_dirs - @$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + @$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -c -o $@ $< @printf "$(COLOR_COM)(CC)$(COLOR_NONE)\t$@\n" # C++ source -> object $(BUILD)/%.o: $(KERNEL)/%.cpp $(HEADERS) @$(MAKE) mkdir_obj_dirs - @$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + @$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -c -o $@ $< @printf "$(COLOR_COM)(CXX)$(COLOR_NONE)\t$@\n" # GAS assembly -> object $(BUILD)/%.o: $(KERNEL)/%.s @@ -166,10 +172,10 @@ $(BUILD)/%.o: $(KERNEL)/%.S @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" # Kernel object -$(PRODUCT)/kernel: $(OBJ) +$(PRODUCT)/$(KERNEL): $(OBJ) @mkdir -p dist @$(LD) -o $@ $(OBJ) $(LDFLAGS) - @$(OBJCP) --only-keep-debug $(PRODUCT)/kernel $(PRODUCT)/panix.sym + @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) # ******************************** # * Kernel Distribution Creation * @@ -257,11 +263,11 @@ docs: # Clear out objects and BIN .PHONY: clean clean: - @echo Cleaning obj directory... - @rm -rf obj - @echo Cleaning bin files... - @rm -rf dist/* - @echo "Done cleaning!" + @printf "$(COLOR_OK)Cleaning objects...$(COLOR_NONE)\n" + $(RM) $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) $(OBJ) $(DEP) + @printf "$(COLOR_OK)Cleaning directories...$(COLOR_NONE)\n" + $(RM) -r $(OBJ_DIRS) + @printf "$(COLOR_OK)Cleaning complete.$(COLOR_NONE)\n" .PHONY: clean-vm clean-vm: From 3693d5da45ce1218ede2e10eed0728d3d425079a Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 21:57:42 -0500 Subject: [PATCH 081/139] Moved more paths to makefile variables --- Makefile | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index ea325f50..e88f64b5 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ COLOR_NONE = \033[m # * Source Code & Directories * # ***************************** -# Directories +# Directories & files BUILD = obj LIBRARY = libs KERNEL = kernel @@ -123,12 +123,12 @@ LDFLAGS := \ # Debug build debug: CXXFLAGS += -DDEBUG -g debug: CFLAGS += -DDEBUG -g -debug: dist/kernel +debug: $(PRODUCT)/$(KERNEL) # Release build release: CXXFLAGS += -O3 -mno-avx release: CFLAGS += -O3 -mno-avx -release: dist/kernel +release: $(PRODUCT)/$(KERNEL) # ************************* # * Kernel Source Objects * @@ -173,7 +173,7 @@ $(BUILD)/%.o: $(KERNEL)/%.S @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" # Kernel object $(PRODUCT)/$(KERNEL): $(OBJ) - @mkdir -p dist + @mkdir -p $(PRODUCT) @$(LD) -o $@ $(OBJ) $(LDFLAGS) @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) @@ -182,9 +182,9 @@ $(PRODUCT)/$(KERNEL): $(OBJ) # ******************************** # Create bootable ISO -iso: $(PRODUCT)/kernel +iso: $(PRODUCT)/$(KERNEL) @mkdir -p iso/boot/grub - @cp dist/kernel iso/boot/ + @cp $(PRODUCT)/$(KERNEL) iso/boot/ @cp boot/grub.cfg iso/boot/grub/grub.cfg @$(MKGRUB) -o $(PRODUCT)/panix.iso iso @rm -rf iso @@ -202,7 +202,7 @@ QEMU_FLAGS = \ QEMU_ARCH = i386 # Virtualbox flags VM_NAME = panix-box -VBOX_VM_FILE=dist/$(VM_NAME)/$(VM_NAME).vbox +VBOX_VM_FILE=$(PRODUCT)/$(VM_NAME)/$(VM_NAME).vbox # VM executable locations VBOX = $(shell command -v VBoxManage) QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) @@ -213,22 +213,22 @@ QEMU = $(shell command -v qemu-system-$(QEMU_ARCH)) # Run Panix in QEMU .PHONY: run -run: $(PRODUCT)/kernel - $(QEMU) \ - -kernel dist/kernel \ +run: $(PRODUCT)/$(KERNEL) + $(QEMU) \ + -kernel $(PRODUCT)/$(KERNEL) \ $(QEMU_FLAGS) # Create Virtualbox VM .PHONY: vbox-create vbox-create: $(PRODUCT)/panix.iso - $(VBOX) createvm --register --name $(VM_NAME) --basefolder $(shell pwd)/dist + $(VBOX) createvm --register --name $(VM_NAME) --basefolder $(shell pwd)/$(PRODUCT) $(VBOX) modifyvm $(VM_NAME) \ --memory 256 --ioapic on --cpus 2 --vram 16 \ --graphicscontroller vboxvga --boot1 disk \ --audiocontroller sb16 --uart1 0x3f8 4 \ --uartmode1 file $(shell pwd)/com1.txt $(VBOX) storagectl $(VM_NAME) --name "DiskDrive" --add ide --bootable on - $(VBOX) storageattach $(VM_NAME) --storagectl "DiskDrive" --port 1 --device 1 --type dvddrive --medium dist/panix.iso + $(VBOX) storageattach $(VM_NAME) --storagectl "DiskDrive" --port 1 --device 1 --type dvddrive --medium $(PRODUCT)/panix.iso .PHONY: vbox-create vbox: vbox-create @@ -244,8 +244,6 @@ debugger: $(PRODUCT)/kernel $(QEMU_FLAGS) > /dev/null &) sleep 1 wmctrl -xr qemu.Qemu-system-$(QEMU_ARCH) -b add,above - # After this start the visual studio debugger - # gdb dist/kernel # **************************** # * Documentation Generation * From b6ae8d1112102586e485aad8a216134f0b5ba4b1 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 22:08:27 -0500 Subject: [PATCH 082/139] Added todo target --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index e88f64b5..a4726c5c 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,8 @@ OBJ = $(patsubst $(KERNEL)/%.cpp, $(BUILD)/%.o, $(CPP_SRC)) \ OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) # Dependency files DEP = $(OBJ:%.o=%.d) +# All files (source, header, etc.) +ALLFILES = $(ATT_SRC) $(NASM_SRC) $(C_SRC) $(CPP_SRC) $(HEADERS) # Include all .d files -include $(DEP) @@ -254,6 +256,10 @@ docs: @echo Generating docs according to the Doxyfile... @doxygen ./Doxyfile +.PHONY: todo +todo: + -@for file in $(ALLFILES:Makefile=); do fgrep -H --color=always -e TODO -e FIXME $$file; done; true + # ******************** # * Cleaning Targets * # ******************** From e5af82412cceeadaaebd5afc7e7800c2798590e3 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 22:15:15 -0500 Subject: [PATCH 083/139] Updated source and header detection --- Makefile | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index a4726c5c..254ec014 100644 --- a/Makefile +++ b/Makefile @@ -28,12 +28,16 @@ PRODUCT = dist SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include -# Source code -ATT_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.s") -NASM_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.S") -C_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.c") -CPP_SRC = $(shell find $(KERNEL) $(LIBRARY) -name "*.cpp") -HEADERS = $(shell find $(INCLUDE) $(LIBRARY) -name "*.hpp" -or -name "*.h") +# Assembly +ATT_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.s") +NASM_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.S") +# C / C++ +C_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.c") +CPP_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.cpp") +# Headers +C_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.h") +CPP_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.hpp") +HEADERS = $(CPP_HDR) $(C_HDR) # ******************* # * i686 Toolchains * @@ -258,7 +262,7 @@ docs: .PHONY: todo todo: - -@for file in $(ALLFILES:Makefile=); do fgrep -H --color=always -e TODO -e FIXME $$file; done; true + -@for file in $(ALLFILES:Makefile=); do fgrep -i -H --color=always -e TODO -e FIXME $$file; done; true # ******************** # * Cleaning Targets * From 83004c186a97b531001065479ea34095185af421 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 22:20:47 -0500 Subject: [PATCH 084/139] Updated Makefile header --- Makefile | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 254ec014..5addb54b 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,13 @@ -# Panix Kernel Makefile -# Compiles the kernel source code located in the kernel/ folder. -# -# TODO: Create seperate makefiles as needed and integrate into one makefile +# ____ _ _ __ _ +# | _ \ __ _ _ __ (_)_ __ | |/ /___ _ __ _ __ ___| | +# | |_) / _` | '_ \| \ \/ / | ' // _ \ '__| '_ \ / _ \ | +# | __/ (_| | | | | |> < | . \ __/ | | | | | __/ | +# |_| \__,_|_| |_|_/_/\_\ |_|\_\___|_| |_| |_|\___|_| # +# Compiles the kernel source code located in the kernel folder. + +# Designed by Keeton Feavel & Micah Switzer +# Copyright the Panix Contributors (c) 2019 .DEFAULT_GOAL := release GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" From 1e3619ac4568a157be04568d5d381cd2dbeceed2 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 1 Dec 2020 22:37:07 -0500 Subject: [PATCH 085/139] Simplified gitignore and code workspace files --- .gitignore | 9 --------- panix.code-workspace | 4 +--- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 96fa7138..8cd864cb 100644 --- a/.gitignore +++ b/.gitignore @@ -16,21 +16,12 @@ *.dylib *.dll -# Fortran module files -*.mod -*.smod - # Compiled Static libraries *.lai *.la *.a *.lib -# Executables -*.exe -*.out -*.app - # Ignore all object and archive files *.[oa] *.bin diff --git a/panix.code-workspace b/panix.code-workspace index 0de1f179..2e07bc2e 100644 --- a/panix.code-workspace +++ b/panix.code-workspace @@ -17,13 +17,11 @@ ], "C_Cpp.clang_format_fallbackStyle": "LLVM", "C_Cpp.default.cppStandard": "c++17", - "C_Cpp.default.cStandard": "c11", + "C_Cpp.default.cStandard": "c17", "C_Cpp.default.intelliSenseMode": "gcc-x86", "doxdocgen.file.copyrightTag": [ "@copyright Copyright the Panix Contributors (c) {year}" ], - "doxdocgen.generic.authorEmail": "keetonfeavel@cedarville.edu", - "doxdocgen.generic.authorName": "Keeton Feavel", "clang-format.fallbackStyle": "Webkit", "C_Cpp.intelliSenseEngineFallback": "Enabled" } From 0f01cc991211a58d46795eea63e330d3daad32df Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Thu, 3 Dec 2020 21:30:59 -0500 Subject: [PATCH 086/139] Moved ISO to variable, made release default target --- Makefile | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 5addb54b..2f8750ca 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,6 @@ # Designed by Keeton Feavel & Micah Switzer # Copyright the Panix Contributors (c) 2019 -.DEFAULT_GOAL := release GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" # ****************************** @@ -28,6 +27,7 @@ COLOR_NONE = \033[m BUILD = obj LIBRARY = libs KERNEL = kernel +ISOIMG = panix.iso SYMBOLS = $(KERNEL).sym PRODUCT = dist SYSROOT = sysroot @@ -129,16 +129,18 @@ LDFLAGS := \ # * Kernel Build Targets * # ************************ -# Debug build -debug: CXXFLAGS += -DDEBUG -g -debug: CFLAGS += -DDEBUG -g -debug: $(PRODUCT)/$(KERNEL) - # Release build +# This will be build by default since it +# is the first target in the Makefile release: CXXFLAGS += -O3 -mno-avx release: CFLAGS += -O3 -mno-avx release: $(PRODUCT)/$(KERNEL) +# Debug build +debug: CXXFLAGS += -DDEBUG -g +debug: CFLAGS += -DDEBUG -g +debug: $(PRODUCT)/$(KERNEL) + # ************************* # * Kernel Source Objects * # ************************* @@ -197,7 +199,7 @@ iso: $(PRODUCT)/$(KERNEL) @mkdir -p iso/boot/grub @cp $(PRODUCT)/$(KERNEL) iso/boot/ @cp boot/grub.cfg iso/boot/grub/grub.cfg - @$(MKGRUB) -o $(PRODUCT)/panix.iso iso + @$(MKGRUB) -o $(PRODUCT)/$(ISOIMG) iso @rm -rf iso # ************************* @@ -231,7 +233,7 @@ run: $(PRODUCT)/$(KERNEL) # Create Virtualbox VM .PHONY: vbox-create -vbox-create: $(PRODUCT)/panix.iso +vbox-create: $(PRODUCT)/$(ISOIMG) $(VBOX) createvm --register --name $(VM_NAME) --basefolder $(shell pwd)/$(PRODUCT) $(VBOX) modifyvm $(VM_NAME) \ --memory 256 --ioapic on --cpus 2 --vram 16 \ @@ -239,7 +241,7 @@ vbox-create: $(PRODUCT)/panix.iso --audiocontroller sb16 --uart1 0x3f8 4 \ --uartmode1 file $(shell pwd)/com1.txt $(VBOX) storagectl $(VM_NAME) --name "DiskDrive" --add ide --bootable on - $(VBOX) storageattach $(VM_NAME) --storagectl "DiskDrive" --port 1 --device 1 --type dvddrive --medium $(PRODUCT)/panix.iso + $(VBOX) storageattach $(VM_NAME) --storagectl "DiskDrive" --port 1 --device 1 --type dvddrive --medium $(PRODUCT)/$(ISOIMG) .PHONY: vbox-create vbox: vbox-create @@ -247,7 +249,7 @@ vbox: vbox-create # Open the connection to qemu and load our kernel-object file with symbols .PHONY: debugger -debugger: $(PRODUCT)/kernel +debugger: $(PRODUCT)/$(KERNEL) # Start QEMU with debugger ($(QEMU) \ -S -s \ From 109ef8c666474fb975d3a3b85dd8028162531382 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 5 Dec 2020 14:05:25 -0500 Subject: [PATCH 087/139] Make magically finds and links .a files in libs --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 2f8750ca..b94aad6f 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,9 @@ CPP_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.cpp") C_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.h") CPP_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.hpp") HEADERS = $(CPP_HDR) $(C_HDR) +# Libraries +LIB_DIRS = $(shell find $(LIBRARY) -name '*.a') +LIBS = $(addprefix -l:, $(LIB_DIRS)) # ******************* # * i686 Toolchains * @@ -123,6 +126,8 @@ LDFLAGS := \ ${PANIX_LDFLAGS} \ -m elf_i386 \ -T kernel/arch/i386/linker.ld \ + -L $(LIBRARY) \ + $(LIBS) \ -lgcc # ************************ From 356a56110d612ba705423c3e9a184701efc1b73f Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 5 Dec 2020 14:29:33 -0500 Subject: [PATCH 088/139] Renamed LIB_DIRS to LIB_A to make more sense --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b94aad6f..8d6a4d32 100644 --- a/Makefile +++ b/Makefile @@ -44,8 +44,8 @@ C_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.h") CPP_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.hpp") HEADERS = $(CPP_HDR) $(C_HDR) # Libraries -LIB_DIRS = $(shell find $(LIBRARY) -name '*.a') -LIBS = $(addprefix -l:, $(LIB_DIRS)) +LIB_A = $(shell find $(LIBRARY) -type f -name "*.a") +LIBS = $(addprefix -l:, $(LIB_A)) # ******************* # * i686 Toolchains * From f7623fcc7ba90139eead6384c90e060f84321df2 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 5 Dec 2020 15:33:07 -0500 Subject: [PATCH 089/139] Fixed Makefile including code in libs --- Makefile | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) mode change 100644 => 100755 Makefile diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 index 8d6a4d32..f7926a58 --- a/Makefile +++ b/Makefile @@ -9,6 +9,9 @@ # Designed by Keeton Feavel & Micah Switzer # Copyright the Panix Contributors (c) 2019 +# Makefile flags +# prevent make from showing "entering/leaving directory" messages +MAKEFLAGS += --no-print-directory GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" # ****************************** @@ -34,18 +37,19 @@ SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include # Assembly -ATT_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.s") -NASM_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.S") +ATT_SRC = $(shell find $(KERNEL) -type f -name "*.s") +NASM_SRC = $(shell find $(KERNEL) -type f -name "*.S") # C / C++ -C_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.c") -CPP_SRC = $(shell find $(KERNEL) $(LIBRARY) -type f -name "*.cpp") +C_SRC = $(shell find $(KERNEL) -type f -name "*.c") +CPP_SRC = $(shell find $(KERNEL) -type f -name "*.cpp") # Headers -C_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.h") -CPP_HDR = $(shell find $(INCLUDE) $(LIBRARY) -type f -name "*.hpp") +C_HDR = $(shell find $(INCLUDE) -type f -name "*.h") +CPP_HDR = $(shell find $(INCLUDE) -type f -name "*.hpp") HEADERS = $(CPP_HDR) $(C_HDR) # Libraries -LIB_A = $(shell find $(LIBRARY) -type f -name "*.a") -LIBS = $(addprefix -l:, $(LIB_A)) +LIB_DIRS = $(shell find $(LIBRARY) -type d) +LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") +LIBS = $(addprefix -l:, $(LIBS_A)) # ******************* # * i686 Toolchains * @@ -151,14 +155,15 @@ debug: $(PRODUCT)/$(KERNEL) # ************************* # All objects -OBJ = $(patsubst $(KERNEL)/%.cpp, $(BUILD)/%.o, $(CPP_SRC)) \ - $(patsubst $(KERNEL)/%.c, $(BUILD)/%.o, $(C_SRC)) \ - $(patsubst $(KERNEL)/%.s, $(BUILD)/%.o, $(ATT_SRC)) \ - $(patsubst $(KERNEL)/%.S, $(BUILD)/%.o, $(NASM_SRC)) +OBJ_C = $(patsubst $(KERNEL)/%.c, $(BUILD)/%.o, $(C_SRC)) +OBJ_CPP = $(patsubst $(KERNEL)/%.cpp, $(BUILD)/%.o, $(CPP_SRC)) +OBJ_ASM = $(patsubst $(KERNEL)/%.s, $(BUILD)/%.o, $(ATT_SRC)) \ + $(patsubst $(KERNEL)/%.S, $(BUILD)/%.o, $(NASM_SRC)) +OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) # Object directories, mirroring source OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) # Dependency files -DEP = $(OBJ:%.o=%.d) +DEP = $(OBJ_CPP:%.o=%.d) $(OBJ_C:%.o=%.d) # All files (source, header, etc.) ALLFILES = $(ATT_SRC) $(NASM_SRC) $(C_SRC) $(CPP_SRC) $(HEADERS) # Include all .d files @@ -190,7 +195,7 @@ $(BUILD)/%.o: $(KERNEL)/%.S @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" # Kernel object -$(PRODUCT)/$(KERNEL): $(OBJ) +$(PRODUCT)/$(KERNEL): $(LIBRARY) $(OBJ) @mkdir -p $(PRODUCT) @$(LD) -o $@ $(OBJ) $(LDFLAGS) @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) From 6f278a8fb778039ccb3e87473d59aa63d1fe98f8 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 5 Dec 2020 20:05:26 -0500 Subject: [PATCH 090/139] Makefiles in libs now called w/ target panix --- Makefile | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index f7926a58..a9afe87e 100755 --- a/Makefile +++ b/Makefile @@ -9,6 +9,8 @@ # Designed by Keeton Feavel & Micah Switzer # Copyright the Panix Contributors (c) 2019 +PROJ_NAME = panix + # Makefile flags # prevent make from showing "entering/leaving directory" messages MAKEFLAGS += --no-print-directory @@ -30,7 +32,7 @@ COLOR_NONE = \033[m BUILD = obj LIBRARY = libs KERNEL = kernel -ISOIMG = panix.iso +ISOIMG = $(PROJ_NAME).iso SYMBOLS = $(KERNEL).sym PRODUCT = dist SYSROOT = sysroot @@ -47,7 +49,7 @@ C_HDR = $(shell find $(INCLUDE) -type f -name "*.h") CPP_HDR = $(shell find $(INCLUDE) -type f -name "*.hpp") HEADERS = $(CPP_HDR) $(C_HDR) # Libraries -LIB_DIRS = $(shell find $(LIBRARY) -type d) +LIB_DIRS = $(shell find $(LIBRARY) -type d -maxdepth 1) LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") LIBS = $(addprefix -l:, $(LIBS_A)) @@ -194,6 +196,12 @@ $(BUILD)/%.o: $(KERNEL)/%.S @$(MAKE) mkdir_obj_dirs @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" +# Kernel Libraries +.PHONY: $(LIBRARY) +$(LIBRARY): + @for dir in $(LIB_DIRS); do \ + $(MAKE) -C $$dir $(PROJ_NAME); \ + done # Kernel object $(PRODUCT)/$(KERNEL): $(LIBRARY) $(OBJ) @mkdir -p $(PRODUCT) @@ -224,7 +232,7 @@ QEMU_FLAGS = \ -serial stdio QEMU_ARCH = i386 # Virtualbox flags -VM_NAME = panix-box +VM_NAME = $(PROJ_NAME)-box VBOX_VM_FILE=$(PRODUCT)/$(VM_NAME)/$(VM_NAME).vbox # VM executable locations VBOX = $(shell command -v VBoxManage) From db4fedf15178964774a21960fb7527cc91d4c071 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 5 Dec 2020 21:00:35 -0500 Subject: [PATCH 091/139] Fixed -L include path --- Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index a9afe87e..c739ce99 100755 --- a/Makefile +++ b/Makefile @@ -132,7 +132,7 @@ LDFLAGS := \ ${PANIX_LDFLAGS} \ -m elf_i386 \ -T kernel/arch/i386/linker.ld \ - -L $(LIBRARY) \ + -L. \ $(LIBS) \ -lgcc @@ -197,10 +197,9 @@ $(BUILD)/%.o: $(KERNEL)/%.S @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" # Kernel Libraries -.PHONY: $(LIBRARY) $(LIBRARY): - @for dir in $(LIB_DIRS); do \ - $(MAKE) -C $$dir $(PROJ_NAME); \ + @for dir in $(LIB_DIRS); do \ + $(MAKE) -s -C $$dir $(PROJ_NAME); \ done # Kernel object $(PRODUCT)/$(KERNEL): $(LIBRARY) $(OBJ) From 021a467b97e2b4bc63c71bde949d7a7cb69b5505 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 5 Dec 2020 22:10:23 -0500 Subject: [PATCH 092/139] Make make make the kernel after the libs --- Makefile | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index c739ce99..f9307bc2 100755 --- a/Makefile +++ b/Makefile @@ -49,9 +49,9 @@ C_HDR = $(shell find $(INCLUDE) -type f -name "*.h") CPP_HDR = $(shell find $(INCLUDE) -type f -name "*.hpp") HEADERS = $(CPP_HDR) $(C_HDR) # Libraries -LIB_DIRS = $(shell find $(LIBRARY) -type d -maxdepth 1) +LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") -LIBS = $(addprefix -l:, $(LIBS_A)) +LIBS = $(addprefix -l:,$(LIBS_A)) # ******************* # * i686 Toolchains * @@ -128,7 +128,7 @@ ASFLAGS := \ ${PANIX_ASFLAGS} \ --32 # Linker flags -LDFLAGS := \ +LDFLAGS = \ ${PANIX_LDFLAGS} \ -m elf_i386 \ -T kernel/arch/i386/linker.ld \ @@ -145,7 +145,7 @@ LDFLAGS := \ # is the first target in the Makefile release: CXXFLAGS += -O3 -mno-avx release: CFLAGS += -O3 -mno-avx -release: $(PRODUCT)/$(KERNEL) +release: kernel # Debug build debug: CXXFLAGS += -DDEBUG -g @@ -197,12 +197,14 @@ $(BUILD)/%.o: $(KERNEL)/%.S @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" # Kernel Libraries -$(LIBRARY): - @for dir in $(LIB_DIRS); do \ - $(MAKE) -s -C $$dir $(PROJ_NAME); \ +.PHONY: kernel +kernel: + @for dir in $(LIB_DIRS); do \ + $(MAKE) -C $$dir $(PROJ_NAME); \ done + @$(MAKE) $(PRODUCT)/$(KERNEL) # Kernel object -$(PRODUCT)/$(KERNEL): $(LIBRARY) $(OBJ) +$(PRODUCT)/$(KERNEL): $(LIBS_A) $(OBJ) @mkdir -p $(PRODUCT) @$(LD) -o $@ $(OBJ) $(LDFLAGS) @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) From 491789f516de1da1c3e656c7cfe85269d6542825 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 5 Dec 2020 22:16:07 -0500 Subject: [PATCH 093/139] Makefile now cleans better (libs, iso, obj) --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f9307bc2..9c365e94 100755 --- a/Makefile +++ b/Makefile @@ -298,9 +298,14 @@ todo: .PHONY: clean clean: @printf "$(COLOR_OK)Cleaning objects...$(COLOR_NONE)\n" - $(RM) $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) $(OBJ) $(DEP) + $(RM) -r $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) $(PRODUCT)/$(ISOIMG) $(BUILD) @printf "$(COLOR_OK)Cleaning directories...$(COLOR_NONE)\n" $(RM) -r $(OBJ_DIRS) + @printf "$(COLOR_OK)Cleaning libraries...$(COLOR_NONE)\n" + @for dir in $(LIB_DIRS); do \ + printf " - " && \ + $(MAKE) -s -C $$dir clean; \ + done @printf "$(COLOR_OK)Cleaning complete.$(COLOR_NONE)\n" .PHONY: clean-vm From 26acabeea499d8d2d27da695736e06e4ba28562c Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 6 Dec 2020 15:57:56 -0500 Subject: [PATCH 094/139] Cleaned up kernel target and obj dir creation --- Makefile | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 9c365e94..37743077 100755 --- a/Makefile +++ b/Makefile @@ -128,7 +128,7 @@ ASFLAGS := \ ${PANIX_ASFLAGS} \ --32 # Linker flags -LDFLAGS = \ +LDFLAGS = \ ${PANIX_LDFLAGS} \ -m elf_i386 \ -T kernel/arch/i386/linker.ld \ @@ -145,12 +145,12 @@ LDFLAGS = \ # is the first target in the Makefile release: CXXFLAGS += -O3 -mno-avx release: CFLAGS += -O3 -mno-avx -release: kernel +release: $(KERNEL) # Debug build debug: CXXFLAGS += -DDEBUG -g debug: CFLAGS += -DDEBUG -g -debug: $(PRODUCT)/$(KERNEL) +debug: $(KERNEL) # ************************* # * Kernel Source Objects * @@ -164,6 +164,8 @@ OBJ_ASM = $(patsubst $(KERNEL)/%.s, $(BUILD)/%.o, $(ATT_SRC)) \ OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) # Object directories, mirroring source OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) +# Create object file directories +OBJ_DIRS_MAKE := mkdir -p $(OBJ_DIRS) # Dependency files DEP = $(OBJ_CPP:%.o=%.d) $(OBJ_C:%.o=%.d) # All files (source, header, etc.) @@ -171,43 +173,38 @@ ALLFILES = $(ATT_SRC) $(NASM_SRC) $(C_SRC) $(CPP_SRC) $(HEADERS) # Include all .d files -include $(DEP) -# Create object file directories -.PHONY: mkdir_obj_dirs -mkdir_obj_dirs: - @mkdir -p $(OBJ_DIRS) - # C source -> object $(BUILD)/%.o: $(KERNEL)/%.c $(HEADERS) - @$(MAKE) mkdir_obj_dirs + @$(OBJ_DIRS_MAKE) @$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -c -o $@ $< @printf "$(COLOR_COM)(CC)$(COLOR_NONE)\t$@\n" # C++ source -> object $(BUILD)/%.o: $(KERNEL)/%.cpp $(HEADERS) - @$(MAKE) mkdir_obj_dirs + @$(OBJ_DIRS_MAKE) @$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -c -o $@ $< @printf "$(COLOR_COM)(CXX)$(COLOR_NONE)\t$@\n" # GAS assembly -> object $(BUILD)/%.o: $(KERNEL)/%.s - @$(MAKE) mkdir_obj_dirs + @$(OBJ_DIRS_MAKE) @$(AS) $(ASFLAGS) -o $@ $< @printf "$(COLOR_COM)(AS)$(COLOR_NONE)\t$@\n" # NASM assembly -> object $(BUILD)/%.o: $(KERNEL)/%.S - @$(MAKE) mkdir_obj_dirs + @$(OBJ_DIRS_MAKE) @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" -# Kernel Libraries -.PHONY: kernel -kernel: - @for dir in $(LIB_DIRS); do \ - $(MAKE) -C $$dir $(PROJ_NAME); \ - done - @$(MAKE) $(PRODUCT)/$(KERNEL) # Kernel object $(PRODUCT)/$(KERNEL): $(LIBS_A) $(OBJ) @mkdir -p $(PRODUCT) @$(LD) -o $@ $(OBJ) $(LDFLAGS) @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) +# Kernel (Linked With Libraries) +.PHONY: $(KERNEL) +$(KERNEL): + @for dir in $(LIB_DIRS); do \ + $(MAKE) -C $$dir $(PROJ_NAME); \ + done + @$(MAKE) $(PRODUCT)/$(KERNEL) # ******************************** # * Kernel Distribution Creation * From 90601279a9655dce3d2fca6be52adb3fa2d30c0f Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 31 Oct 2020 09:39:15 -0400 Subject: [PATCH 095/139] Switch to liballoc --- .gitmodules | 3 + kernel/main.cpp | 1 - kernel/mem/heap.cpp | 212 ------------------------ liballoc | 1 + sysroot/usr/include/kernel/mem/heap.hpp | 41 +---- 5 files changed, 6 insertions(+), 252 deletions(-) create mode 100644 .gitmodules delete mode 100644 kernel/mem/heap.cpp create mode 160000 liballoc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..daf29edb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "liballoc"] + path = liballoc + url = https://github.com/blanham/liballoc.git diff --git a/kernel/main.cpp b/kernel/main.cpp index 01bb79f0..c0c45275 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -97,7 +97,6 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma px_isr_install(); // Initialize Interrupt Service Requests px_rs232_init(RS_232_COM1); // RS232 Serial px_paging_init(0); // Initialize paging service (0 is placeholder) - px_heap_init(32*PAGE_SIZE); // Initialize the kernel heap px_kbd_init(); // Initialize PS/2 Keyboard px_rtc_init(); // Initialize Real Time Clock px_timer_init(1000); // Programmable Interrupt Timer (1ms) diff --git a/kernel/mem/heap.cpp b/kernel/mem/heap.cpp deleted file mode 100644 index b5078096..00000000 --- a/kernel/mem/heap.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @file heap.cpp - * @author Goswin von Brederlow (goswin-v-b@web.de) - * @author Keeton Feavel (keetonfeavel@cedarville.edu) - * @brief - * @version 0.3 - * @date 2019-11-22 - * - * @copyright Copyright the Panix Contributors (c) 2019 - * Code shamelessly taken from the OSDev Wiki. The article - * can be found at the link below. - * - * https://wiki.osdev.org/User:Mrvn/LinkedListBucketHeapImplementation - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define NUM_SLOTS 1024 -#define CONTAINER(C, l, v) ((C*)(((char*)v) - (intptr_t)&(((C*)0)->l))) - -size_t mem_free = 0; -size_t mem_used = 0; -size_t mem_meta = 0; - -px_heap_chunk_t* free_chunk[NUM_SIZES] = { NULL }; -px_heap_chunk_t* first = NULL; -px_heap_chunk_t* last = NULL; - -void* slot[NUM_SLOTS] = { NULL }; - -// Function declarations -void check(void); - -static void px_memory_chunk_init(px_heap_chunk_t* chunk) { - px_debugf("%s(0x%p)\n", __FUNCTION__, chunk); - dlist_init(&chunk->all); - chunk->used = 0; - dlist_init(&chunk->free); -} - -static size_t px_memory_chunk_size(const px_heap_chunk_t* chunk) { - px_debugf("%s(0x%p)\n", __FUNCTION__, chunk); - char* end = (char*)(chunk->all.next); - char* start = (char*)(&chunk->all); - return (end - start) - HEADER_SIZE; -} - -static int px_memory_chunk_slot(size_t size) { - int n = -1; - while(size > 0) { - ++n; - size /= 2; - } - return n; -} - -static void px_remove_free(px_heap_chunk_t* chunk) { - size_t len = px_memory_chunk_size(chunk); - int n = px_memory_chunk_slot(len); - px_debugf("%s(0x%p) : removing chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); - DLIST_REMOVE_FROM(&free_chunk[n], chunk, free); - mem_free -= len - HEADER_SIZE; -} - -static void px_push_free(px_heap_chunk_t* chunk) { - size_t len = px_memory_chunk_size(chunk); - int n = px_memory_chunk_slot(len); - px_debugf("%s(0x%p) : adding chunk 0x%lx [%d]\n", __FUNCTION__, chunk, len, n); - DLIST_PUSH(&free_chunk[n], chunk, free); - mem_free += len - HEADER_SIZE; -} - -void check(void) { - int i; - px_heap_chunk_t* t = last; - - DLIST_ITERATOR_BEGIN(first, all, it) { - assert(CONTAINER(px_heap_chunk_t, all, it->all.prev) == t); - t = it; - } DLIST_ITERATOR_END(it); - - for (i = 0; i < NUM_SIZES; ++i) { - if (free_chunk[i]) { - t = CONTAINER(px_heap_chunk_t, free, free_chunk[i]->free.prev); - DLIST_ITERATOR_BEGIN(free_chunk[i], free, it) { - assert(CONTAINER(px_heap_chunk_t, free, it->free.prev) == t); - t = it; - } DLIST_ITERATOR_END(it); - } - } -} - -void px_heap_init(size_t size) { - // Request a new page with the given size. Get the page address. - void* mem = px_get_new_page(size); - - // Use the page we got as the memory for the heap - char* mem_start = (char*)(((uintptr_t)mem + ALIGN - 1) & (~(ALIGN - 1))); - char* mem_end = (char*)(((uintptr_t)mem + size) & (~(ALIGN - 1))); - first = (px_heap_chunk_t*)mem_start; - px_heap_chunk_t* second = first + 1; - last = ((px_heap_chunk_t*)mem_end) - 1; - - // Initialize the heap chunks - px_memory_chunk_init(first); - px_memory_chunk_init(second); - px_memory_chunk_init(last); - dlist_insert_after(&first->all, &second->all); - dlist_insert_after(&second->all, &last->all); - - // make first/last as used so they never get merged - first->used = 1; - last->used = 1; - // Get the sizes and number of chunks - size_t len = px_memory_chunk_size(second); - int n = px_memory_chunk_slot(len); - px_debugf("%s(0x%p, 0x%lx) : adding chunk 0x%lx [%d]\n", __FUNCTION__, mem, size, len, n); - // Push them onto the linked list and update tracking variables - DLIST_PUSH(&free_chunk[n], second, free); - mem_free = len - HEADER_SIZE; - mem_meta = sizeof(px_heap_chunk_t) * 2 + HEADER_SIZE; -} - -void* malloc(size_t size) { - px_debugf("%s(0x%lx)\n", __FUNCTION__, size); - size = (size + ALIGN - 1) & (~(ALIGN - 1)); - - if (size < MIN_SIZE) { - size = MIN_SIZE; - } - - int n = px_memory_chunk_slot(size - 1) + 1; - - if (n >= NUM_SIZES) { - return NULL; - } - - while(!free_chunk[n]) { - ++n; - if (n >= NUM_SIZES) return NULL; - } - - px_heap_chunk_t* chunk = DLIST_POP(&free_chunk[n], free); - size_t size2 = px_memory_chunk_size(chunk); - px_debugf("@ 0x%p [0x%lx]\n", chunk, size2); - size_t len = 0; - - if (size + sizeof(px_heap_chunk_t) <= size2) { - px_heap_chunk_t* chunk2 = (px_heap_chunk_t*)(((char*)chunk) + HEADER_SIZE + size); - px_memory_chunk_init(chunk2); - dlist_insert_after(&chunk->all, &chunk2->all); - len = px_memory_chunk_size(chunk2); - n = px_memory_chunk_slot(len); - px_debugf(" adding chunk @ 0x%p 0x%lx [%d]\n", chunk2, len, n); - DLIST_PUSH(&free_chunk[n], chunk2, free); - mem_meta += HEADER_SIZE; - mem_free += len - HEADER_SIZE; - } - - chunk->used = 1; - memset(chunk->data, 0xAA, size); - px_debugf("AAAA\n"); - mem_free -= size2; - mem_used += size2 - len - HEADER_SIZE; - px_debugf(" = %p [%p]\n", chunk->data, chunk); - return chunk->data; -} - -void free(void* mem) { - px_heap_chunk_t* chunk = (px_heap_chunk_t*)((char*)mem - HEADER_SIZE); - px_heap_chunk_t* next = CONTAINER(px_heap_chunk_t, all, chunk->all.next); - px_heap_chunk_t* prev = CONTAINER(px_heap_chunk_t, all, chunk->all.prev); - px_debugf("%s(0x%p): 0x@%p 0x%lx [%d]\n", - __FUNCTION__, - mem, - chunk, - px_memory_chunk_size(chunk), - px_memory_chunk_slot(px_memory_chunk_size(chunk)) - ); - mem_used -= px_memory_chunk_size(chunk); - - if (next->used == 0) { - // merge in next - px_remove_free(next); - dlist_remove(&next->all); - memset(next, 0xDD, sizeof(px_heap_chunk_t)); - mem_meta -= HEADER_SIZE; - mem_free += HEADER_SIZE; - } - if (prev->used == 0) { - // merge to prev - px_remove_free(prev); - dlist_remove(&chunk->all); - memset(chunk, 0xDD, sizeof(px_heap_chunk_t)); - px_push_free(prev); - mem_meta -= HEADER_SIZE; - mem_free += HEADER_SIZE; - } else { - // make chunk as free - chunk->used = 0; - dlist_init(&chunk->free); - px_push_free(chunk); - } -} diff --git a/liballoc b/liballoc new file mode 160000 index 00000000..f6c2d145 --- /dev/null +++ b/liballoc @@ -0,0 +1 @@ +Subproject commit f6c2d1454f43d1f04452a5ae62302f903a78a9b1 diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 260733c8..18831b49 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -16,43 +16,6 @@ #ifndef PANIX_MEM_HEAP #define PANIX_MEM_HEAP -#include -#include +#include -typedef struct px_heap_chunk { - DList all; - int used; - union { - char data[0]; - DList free; - }; -} px_heap_chunk_t; - -enum { - NUM_SIZES = 32, - ALIGN = 4, - MIN_SIZE = sizeof(DList), - HEADER_SIZE = __builtin_offsetof(px_heap_chunk_t, data) -}; - -/** - * @brief Initializes the kernel heap. - * - * @param size Number of bytes to be used for the heap. - */ -void px_heap_init(size_t size); -/** - * @brief Dynamically allocate memory. - * - * @param size Number of bytes to be allocated. - * @return void* Address of allocated memory. - */ -void* malloc(size_t size); -/** - * @brief Frees dynamically allocated memory - * - * @param mem Address of memory to be freed. - */ -void free(void* mem); - -#endif /* PANIX_MEM_HEAP */ \ No newline at end of file +#endif /* PANIX_MEM_HEAP */ From ff986cea3a833ade2a64c3b84cd846a4283664b2 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Tue, 10 Nov 2020 20:56:56 -0500 Subject: [PATCH 096/139] Add missing wrapper for liballoc --- kernel/mem/liballoc_impl.cpp | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 kernel/mem/liballoc_impl.cpp diff --git a/kernel/mem/liballoc_impl.cpp b/kernel/mem/liballoc_impl.cpp new file mode 100644 index 00000000..db3ef611 --- /dev/null +++ b/kernel/mem/liballoc_impl.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +static px_mutex_t lock = { 0 }; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * lock the allocator. + */ +int liballoc_lock() +{ + int old_errno = errno; + int result = px_mutex_lock(&lock); + errno = old_errno; + return result; +} + +/* + * unlock the allocator. + */ +int liballoc_unlock() +{ + int old_errno = errno; + int result = px_mutex_unlock(&lock); + errno = old_errno; + return result; +} + +/* + * get a new page or pages. + */ +void *liballoc_alloc(int count) +{ + return px_get_new_page(count * PAGE_SIZE - 1); +} + +/* + * free a page or pages. + */ +int liballoc_free(void *page, int count) +{ + px_free_page(page, count * PAGE_SIZE - 1); + return 0; +} + +#ifdef __cplusplus +} +#endif + From ba33e3c0e3840166a16b007bd483aca89a79849c Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 6 Dec 2020 17:34:27 -0500 Subject: [PATCH 097/139] Integrated Liballoc into Panix --- .gitmodules | 7 ++-- Makefile | 53 ++++++++++++------------- liballoc | 1 - libs/liballoc | 1 + sysroot/usr/include/kernel/mem/heap.hpp | 52 +++++++++++++++++++++++- 5 files changed, 81 insertions(+), 33 deletions(-) delete mode 160000 liballoc create mode 160000 libs/liballoc diff --git a/.gitmodules b/.gitmodules index daf29edb..b18221a0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ -[submodule "liballoc"] - path = liballoc - url = https://github.com/blanham/liballoc.git +[submodule "libs/liballoc"] + path = libs/liballoc + url = https://github.com/panix-os/liballoc.git + branch = panix diff --git a/Makefile b/Makefile index 37743077..bd5f8531 100755 --- a/Makefile +++ b/Makefile @@ -58,13 +58,14 @@ LIBS = $(addprefix -l:,$(LIBS_A)) # ******************* # Compilers/Assemblers/Linkers -NASM = $(shell command -v nasm) -AS = $(shell command -v i686-elf-as) -CC = $(shell command -v i686-elf-gcc) -CXX = $(shell command -v i686-elf-g++) -LD = $(shell command -v i686-elf-ld) -OBJCP = $(shell command -v i686-elf-objcopy) -MKGRUB = $(shell command -v grub-mkrescue) +export NASM := $(shell command -v nasm) +export AS := $(shell command -v i686-elf-as) +export AR := $(shell command -v i686-elf-ar) +export CC := $(shell command -v i686-elf-gcc) +export CXX := $(shell command -v i686-elf-g++) +export LD := $(shell command -v i686-elf-ld) +export OBJCP := $(shell command -v i686-elf-objcopy) +export MKGRUB := $(shell command -v grub-mkrescue) # ******************* # * Toolchain Flags * @@ -92,31 +93,24 @@ CWARNINGS := \ -Wnested-externs \ -Wstrict-prototypes \ -Wmissing-prototypes \ -# Common (C & C++) flags -FLAGS := \ +# C flags (include directory) +CFLAGS := \ -m32 \ -nostdlib \ -nodefaultlibs \ - -fpermissive \ -ffreestanding \ -fstack-protector-all \ - -fno-rtti \ -fno-builtin \ - -fno-exceptions \ - -fno-use-cxa-atexit \ - -fno-omit-frame-pointer -# C flags (include directory) -CFLAGS := \ - ${FLAGS} \ + -fno-omit-frame-pointer \ ${PANIX_CFLAGS} \ - ${WARNINGS} \ - $(CWARNINGS) \ - -std=c17 + ${WARNINGS} # C++ flags -CXXFLAGS := \ - ${FLAGS} \ - ${PANIX_CXXFLAGS} \ - ${WARNINGS} \ +CXXFLAGS := \ + ${PANIX_CXXFLAGS} \ + -fpermissive \ + -fno-rtti \ + -fno-exceptions \ + -fno-use-cxa-atexit \ -std=c++17 # C / C++ pre-processor flags CPPFLAGS := \ @@ -176,30 +170,33 @@ ALLFILES = $(ATT_SRC) $(NASM_SRC) $(C_SRC) $(CPP_SRC) $(HEADERS) # C source -> object $(BUILD)/%.o: $(KERNEL)/%.c $(HEADERS) @$(OBJ_DIRS_MAKE) - @$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -c -o $@ $< @printf "$(COLOR_COM)(CC)$(COLOR_NONE)\t$@\n" + @$(CC) $(CPPFLAGS) $(CFLAGS) $(CWARNINGS) -std=c17 -MMD -c -o $@ $< # C++ source -> object $(BUILD)/%.o: $(KERNEL)/%.cpp $(HEADERS) @$(OBJ_DIRS_MAKE) - @$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -c -o $@ $< @printf "$(COLOR_COM)(CXX)$(COLOR_NONE)\t$@\n" + @$(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -MMD -c -o $@ $< # GAS assembly -> object $(BUILD)/%.o: $(KERNEL)/%.s @$(OBJ_DIRS_MAKE) - @$(AS) $(ASFLAGS) -o $@ $< @printf "$(COLOR_COM)(AS)$(COLOR_NONE)\t$@\n" + @$(AS) $(ASFLAGS) -o $@ $< # NASM assembly -> object $(BUILD)/%.o: $(KERNEL)/%.S @$(OBJ_DIRS_MAKE) - @$(NASM) -f elf32 -o $@ $< @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" + @$(NASM) -f elf32 -o $@ $< # Kernel object $(PRODUCT)/$(KERNEL): $(LIBS_A) $(OBJ) @mkdir -p $(PRODUCT) + @printf "$(COLOR_COM)(LD)$(COLOR_NONE)\t$@\n" @$(LD) -o $@ $(OBJ) $(LDFLAGS) + @printf "$(COLOR_COM)(OBJCP)$(COLOR_NONE)\t$@\n" @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) # Kernel (Linked With Libraries) .PHONY: $(KERNEL) +$(KERNEL): export CFLAGS += $(CWARNINGS) $(KERNEL): @for dir in $(LIB_DIRS); do \ $(MAKE) -C $$dir $(PROJ_NAME); \ diff --git a/liballoc b/liballoc deleted file mode 160000 index f6c2d145..00000000 --- a/liballoc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f6c2d1454f43d1f04452a5ae62302f903a78a9b1 diff --git a/libs/liballoc b/libs/liballoc new file mode 160000 index 00000000..98c2e249 --- /dev/null +++ b/libs/liballoc @@ -0,0 +1 @@ +Subproject commit 98c2e249d431608e3d7d4aca23f41412972de18a diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 18831b49..402c99b7 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -16,6 +16,56 @@ #ifndef PANIX_MEM_HEAP #define PANIX_MEM_HEAP -#include +#include + +extern "C" +{ + +/** + * @brief This function is supposed to lock the memory data structures. It + * could be as simple as disabling interrupts or acquiring a spinlock. + * It's up to you to decide. + * + * @return 0 if the lock was acquired successfully. Anything else is + * failure. + */ +int liballoc_lock(); + +/** + * @brief This function unlocks what was previously locked by the liballoc_lock + * function. If it disabled interrupts, it enables interrupts. If it + * had acquiried a spinlock, it releases the spinlock. etc. + * + * @return 0 if the lock was successfully released. + */ +int liballoc_unlock(); + +/** + * @brief This is the hook into the local system which allocates pages. It + * accepts an integer parameter which is the number of pages + * required. The page size was set up in the liballoc_init function. + * + * @return NULL if the pages were not allocated. + * @return A pointer to the allocated memory. + */ +void* liballoc_alloc(int); + +/** + * @brief This frees previously allocated memory. The void* parameter passed + * to the function is the exact same value returned from a previous + * liballoc_alloc call. + * + * The integer value is the number of pages to free. + * + * @return 0 if the memory was successfully freed. + */ +int liballoc_free(void*,int); + +extern void *malloc(size_t); +extern void *realloc(void *, size_t); +extern void *calloc(size_t, size_t); +extern void free(void *); + +} #endif /* PANIX_MEM_HEAP */ From 557f68f6834195078ef3a0d9ff1ef4aaee5e8ef3 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 6 Dec 2020 17:36:52 -0500 Subject: [PATCH 098/139] Make codefactor happy Removed redundant whitespace --- sysroot/usr/include/kernel/mem/heap.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 402c99b7..8f1bd2a7 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -20,7 +20,6 @@ extern "C" { - /** * @brief This function is supposed to lock the memory data structures. It * could be as simple as disabling interrupts or acquiring a spinlock. @@ -65,7 +64,6 @@ extern void *malloc(size_t); extern void *realloc(void *, size_t); extern void *calloc(size_t, size_t); extern void free(void *); - } #endif /* PANIX_MEM_HEAP */ From af4b1b08efc4996a794e001152d2bfb907ea0254 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 6 Dec 2020 17:38:22 -0500 Subject: [PATCH 099/139] Fix Makefile whitespace issues --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index bd5f8531..c3a012ab 100755 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ CWARNINGS := \ -Wstrict-prototypes \ -Wmissing-prototypes \ # C flags (include directory) -CFLAGS := \ +CFLAGS := \ -m32 \ -nostdlib \ -nodefaultlibs \ @@ -102,11 +102,11 @@ CFLAGS := \ -fstack-protector-all \ -fno-builtin \ -fno-omit-frame-pointer \ - ${PANIX_CFLAGS} \ + ${PANIX_CFLAGS} \ ${WARNINGS} # C++ flags -CXXFLAGS := \ - ${PANIX_CXXFLAGS} \ +CXXFLAGS := \ + ${PANIX_CXXFLAGS} \ -fpermissive \ -fno-rtti \ -fno-exceptions \ From c38b212f6f02e270973040029f3f6732d02cb714 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 6 Dec 2020 17:44:05 -0500 Subject: [PATCH 100/139] Swapped strcpy parameters --- kernel/lib/string.cpp | 2 +- sysroot/usr/include/kernel/lib/string.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/lib/string.cpp b/kernel/lib/string.cpp index cd93c152..89a0600f 100644 --- a/kernel/lib/string.cpp +++ b/kernel/lib/string.cpp @@ -31,7 +31,7 @@ char* strcat(const char *s1, const char *s2) { return result; } -void strcpy(const char* source, char* destination) { +void strcpy(char* destination, const char* source) { int i = 0; while (source[i] != '\0') { destination[i] = source[i]; diff --git a/sysroot/usr/include/kernel/lib/string.hpp b/sysroot/usr/include/kernel/lib/string.hpp index 34c5542f..8d185983 100644 --- a/sysroot/usr/include/kernel/lib/string.hpp +++ b/sysroot/usr/include/kernel/lib/string.hpp @@ -28,7 +28,7 @@ int strlen(const char* s); * @param source String to be copied * @param destination Location where string will be copied */ -void strcpy(const char* source, char* destination); +void strcpy(char* destination, const char* source); /** * @brief Concatanates string one onto string two. * From 0933ab752a2219d340328a20f90c683f0dea94dd Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 6 Dec 2020 21:01:06 -0500 Subject: [PATCH 101/139] Fixes px_sem_getval unused variable --- kernel/lib/semaphore.cpp | 9 +++------ sysroot/usr/include/kernel/lib/semaphore.hpp | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 4c52dd9a..a119620e 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -131,16 +131,13 @@ int px_sem_post(px_sem_t *sem) { return 0; } -uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val) { - // FIXME: I don't think val should be unused? - (void)val; +int px_sem_getval(px_sem_t *sem, uint32_t *val) { // Check if the semaphore is valid if (sem == NULL) { errno = EINVAL; return -1; } - uint32_t count = -1; - __atomic_load(&sem->count, &count, __ATOMIC_ACQUIRE); - return count; + __atomic_load(&sem->count, &val, __ATOMIC_ACQUIRE); + return 0; } diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index feea671d..b768fafd 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -79,11 +79,11 @@ int px_sem_post(px_sem_t *sem); * @brief Gets the counter value from a semaphore structure. * * @param sem Reference semaphore - * @param val + * @param val Pointer to the semaphore value variable * @return int Returns 0 on success and -1 on failure. * When an error occurs errno is set. */ -uint32_t px_sem_getval(px_sem_t *sem, uint32_t *val); +int px_sem_getval(px_sem_t *sem, uint32_t *val); /** * @brief Destroys a semaphore by removing it from memory. * From 5a954deb58bf3cf59d9338a44e3c06d1205d3820 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 8 Dec 2020 22:00:52 -0500 Subject: [PATCH 102/139] Moves kernel compilation into separate Makefile --- Makefile | 101 ++++++++++------------------------------------- kernel/Makefile | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 80 deletions(-) create mode 100644 kernel/Makefile diff --git a/Makefile b/Makefile index c3a012ab..dfae8000 100755 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -# ____ _ _ __ _ -# | _ \ __ _ _ __ (_)_ __ | |/ /___ _ __ _ __ ___| | -# | |_) / _` | '_ \| \ \/ / | ' // _ \ '__| '_ \ / _ \ | -# | __/ (_| | | | | |> < | . \ __/ | | | | | __/ | -# |_| \__,_|_| |_|_/_/\_\ |_|\_\___|_| |_| |_|\___|_| +# ____ _ +# | _ \ __ _ _ __ (_)_ __ +# | |_) / _` | '_ \| \ \/ / +# | __/ (_| | | | | |> < +# |_| \__,_|_| |_|_/_/\_\ # # Compiles the kernel source code located in the kernel folder. @@ -13,16 +13,16 @@ PROJ_NAME = panix # Makefile flags # prevent make from showing "entering/leaving directory" messages -MAKEFLAGS += --no-print-directory -GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" +export MAKEFLAGS += --no-print-directory +export GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" # ****************************** # * Compiler Output Formatting * # ****************************** -COLOR_COM = \033[0;34m -COLOR_OK = \033[0;32m -COLOR_NONE = \033[m +export COLOR_COM = \033[0;34m +export COLOR_OK = \033[0;32m +export COLOR_NONE = \033[m # ***************************** # * Source Code & Directories * @@ -38,20 +38,9 @@ PRODUCT = dist SYSROOT = sysroot INCLUDE = $(SYSROOT)/usr/include -# Assembly -ATT_SRC = $(shell find $(KERNEL) -type f -name "*.s") -NASM_SRC = $(shell find $(KERNEL) -type f -name "*.S") -# C / C++ -C_SRC = $(shell find $(KERNEL) -type f -name "*.c") -CPP_SRC = $(shell find $(KERNEL) -type f -name "*.cpp") -# Headers -C_HDR = $(shell find $(INCLUDE) -type f -name "*.h") -CPP_HDR = $(shell find $(INCLUDE) -type f -name "*.hpp") -HEADERS = $(CPP_HDR) $(C_HDR) # Libraries -LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) -LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") -LIBS = $(addprefix -l:,$(LIBS_A)) +export LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) +export LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") # ******************* # * i686 Toolchains * @@ -73,7 +62,7 @@ export MKGRUB := $(shell command -v grub-mkrescue) # Warning flags # (Disable unused functions warning) -WARNINGS := \ +export WARNINGS := \ -Wall \ -Werror \ -Wextra \ @@ -89,12 +78,12 @@ WARNINGS := \ # Flags to be added later # -Wconversion # C only warnings -CWARNINGS := \ +export CWARNINGS := \ -Wnested-externs \ -Wstrict-prototypes \ -Wmissing-prototypes \ # C flags (include directory) -CFLAGS := \ +export CFLAGS := \ -m32 \ -nostdlib \ -nodefaultlibs \ @@ -105,7 +94,7 @@ CFLAGS := \ ${PANIX_CFLAGS} \ ${WARNINGS} # C++ flags -CXXFLAGS := \ +export CXXFLAGS := \ ${PANIX_CXXFLAGS} \ -fpermissive \ -fno-rtti \ @@ -113,21 +102,18 @@ CXXFLAGS := \ -fno-use-cxa-atexit \ -std=c++17 # C / C++ pre-processor flags -CPPFLAGS := \ +export CPPFLAGS := \ ${PANIX_CPPFLAGS} \ - -D VERSION=\"$(GIT_VERSION)\" \ - -I ${SYSROOT}/usr/include/kernel/ + -D VERSION=\"$(GIT_VERSION)\" # Assembler flags -ASFLAGS := \ +export ASFLAGS := \ ${PANIX_ASFLAGS} \ --32 # Linker flags -LDFLAGS = \ +export LDFLAGS := \ ${PANIX_LDFLAGS} \ -m elf_i386 \ - -T kernel/arch/i386/linker.ld \ -L. \ - $(LIBS) \ -lgcc # ************************ @@ -150,58 +136,13 @@ debug: $(KERNEL) # * Kernel Source Objects * # ************************* -# All objects -OBJ_C = $(patsubst $(KERNEL)/%.c, $(BUILD)/%.o, $(C_SRC)) -OBJ_CPP = $(patsubst $(KERNEL)/%.cpp, $(BUILD)/%.o, $(CPP_SRC)) -OBJ_ASM = $(patsubst $(KERNEL)/%.s, $(BUILD)/%.o, $(ATT_SRC)) \ - $(patsubst $(KERNEL)/%.S, $(BUILD)/%.o, $(NASM_SRC)) -OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) -# Object directories, mirroring source -OBJ_DIRS = $(subst $(KERNEL), $(BUILD), $(shell find $(KERNEL) -type d)) -# Create object file directories -OBJ_DIRS_MAKE := mkdir -p $(OBJ_DIRS) -# Dependency files -DEP = $(OBJ_CPP:%.o=%.d) $(OBJ_C:%.o=%.d) -# All files (source, header, etc.) -ALLFILES = $(ATT_SRC) $(NASM_SRC) $(C_SRC) $(CPP_SRC) $(HEADERS) -# Include all .d files --include $(DEP) - -# C source -> object -$(BUILD)/%.o: $(KERNEL)/%.c $(HEADERS) - @$(OBJ_DIRS_MAKE) - @printf "$(COLOR_COM)(CC)$(COLOR_NONE)\t$@\n" - @$(CC) $(CPPFLAGS) $(CFLAGS) $(CWARNINGS) -std=c17 -MMD -c -o $@ $< -# C++ source -> object -$(BUILD)/%.o: $(KERNEL)/%.cpp $(HEADERS) - @$(OBJ_DIRS_MAKE) - @printf "$(COLOR_COM)(CXX)$(COLOR_NONE)\t$@\n" - @$(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -MMD -c -o $@ $< -# GAS assembly -> object -$(BUILD)/%.o: $(KERNEL)/%.s - @$(OBJ_DIRS_MAKE) - @printf "$(COLOR_COM)(AS)$(COLOR_NONE)\t$@\n" - @$(AS) $(ASFLAGS) -o $@ $< -# NASM assembly -> object -$(BUILD)/%.o: $(KERNEL)/%.S - @$(OBJ_DIRS_MAKE) - @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" - @$(NASM) -f elf32 -o $@ $< -# Kernel object -$(PRODUCT)/$(KERNEL): $(LIBS_A) $(OBJ) - @mkdir -p $(PRODUCT) - @printf "$(COLOR_COM)(LD)$(COLOR_NONE)\t$@\n" - @$(LD) -o $@ $(OBJ) $(LDFLAGS) - @printf "$(COLOR_COM)(OBJCP)$(COLOR_NONE)\t$@\n" - @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) # Kernel (Linked With Libraries) .PHONY: $(KERNEL) -$(KERNEL): export CFLAGS += $(CWARNINGS) $(KERNEL): @for dir in $(LIB_DIRS); do \ $(MAKE) -C $$dir $(PROJ_NAME); \ done - @$(MAKE) $(PRODUCT)/$(KERNEL) + @$(MAKE) -C $(KERNEL) $(KERNEL) # ******************************** # * Kernel Distribution Creation * diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 00000000..141c253d --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,102 @@ +# ____ _ _ __ _ +# | _ \ __ _ _ __ (_)_ __ | |/ /___ _ __ _ __ ___| | +# | |_) / _` | '_ \| \ \/ / | ' // _ \ '__| '_ \ / _ \ | +# | __/ (_| | | | | |> < | . \ __/ | | | | | __/ | +# |_| \__,_|_| |_|_/_/\_\ |_|\_\___|_| |_| |_|\___|_| +# +# Compiles the kernel source code located in the kernel folder. + +# Designed by Keeton Feavel & Micah Switzer +# Copyright the Panix Contributors (c) 2019 + +PROJ_NAME = panix + +# ***************************** +# * Source Code & Directories * +# ***************************** + +# Directories & files +BUILD = ../obj +KERNEL = kernel +SYMBOLS = $(KERNEL).sym +PRODUCT = ../dist +SYSROOT = ../sysroot +INCLUDE = $(SYSROOT)/usr/include + +# Assembly +ATT_SRC = $(shell find . -type f -name "*.s" | sed "s|^\./||") +NASM_SRC = $(shell find . -type f -name "*.S" | sed "s|^\./||") +# C / C++ +C_SRC = $(shell find . -type f -name "*.c" | sed "s|^\./||") +CPP_SRC = $(shell find . -type f -name "*.cpp" | sed "s|^\./||") +# Headers +C_HDR = $(shell find $(INCLUDE) -type f -name "*.h" | sed "s|^\./||") +CPP_HDR = $(shell find $(INCLUDE) -type f -name "*.hpp" | sed "s|^\./||") +HEADERS = $(CPP_HDR) $(C_HDR) +#Libraries +LIBS_B = $(addprefix ../, $(LIBS_A)) +LIBS = $(addprefix -l:,$(LIBS_B)) +# The `| sed "s|^\./||"` command is included to remove the leading +# ./ from all of the paths so that the objects are generated +# properly. Otherwise the object directory is "obj." and not "obj" + +# ******************* +# * Toolchain Flags * +# ******************* + +CPPFLAGS += \ + -I ${SYSROOT}/usr/include/kernel/ + +LDFLAGS += \ + -T arch/i386/linker.ld \ + $(LIBS) \ + +# ************************* +# * Kernel Source Objects * +# ************************* + +# All objects +OBJ_C = $(patsubst %.c, $(BUILD)/%.o, $(C_SRC)) +OBJ_CPP = $(patsubst %.cpp, $(BUILD)/%.o, $(CPP_SRC)) +OBJ_ASM = $(patsubst %.s, $(BUILD)/%.o, $(ATT_SRC)) \ + $(patsubst %.S, $(BUILD)/%.o, $(NASM_SRC)) +OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) +# Object directories, mirroring source +OBJ_DIRS = $(addprefix $(BUILD), $(shell find . -type d | sed "s|^\.||")) +# Create object file directories +OBJ_DIRS_MAKE := mkdir -p $(OBJ_DIRS) +# Dependency files +DEP = $(OBJ_CPP:%.o=%.d) $(OBJ_C:%.o=%.d) +# All files (source, header, etc.) +ALLFILES = $(ATT_SRC) $(NASM_SRC) $(C_SRC) $(CPP_SRC) $(HEADERS) +# Include all .d files +-include $(DEP) + +# C source -> object +$(BUILD)/%.o: %.c $(HEADERS) + @$(OBJ_DIRS_MAKE) + @printf "$(COLOR_COM)(CC)$(COLOR_NONE)\t$@\n" + @$(CC) $(CPPFLAGS) $(CFLAGS) $(CWARNINGS) -std=c17 -MMD -c -o $@ $< +# C++ source -> object +$(BUILD)/%.o: %.cpp $(HEADERS) + @$(OBJ_DIRS_MAKE) + @printf "$(COLOR_COM)(CXX)$(COLOR_NONE)\t$@\n" + @$(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -MMD -c -o $@ $< +# GAS assembly -> object +$(BUILD)/%.o: %.s + @$(OBJ_DIRS_MAKE) + @printf "$(COLOR_COM)(AS)$(COLOR_NONE)\t$@\n" + @$(AS) $(ASFLAGS) -o $@ $< +# NASM assembly -> object +$(BUILD)/%.o: %.S + @$(OBJ_DIRS_MAKE) + @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" + @$(NASM) -f elf32 -o $@ $< +# Kernel object +$(KERNEL): $(OBJ) + @mkdir -p $(PRODUCT) + @printf "$(COLOR_COM)(LD)$(COLOR_NONE)\t$@\n" + $(LD) -o $@ $(OBJ) $(LDFLAGS) + @mv $(KERNEL) $(PRODUCT)/$(KERNEL) + @printf "$(COLOR_COM)(OBJCP)$(COLOR_NONE)\t$@\n" + @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) From cce2fde50b7c3039af716c99227abcbd68d659d3 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 8 Dec 2020 22:11:46 -0500 Subject: [PATCH 103/139] Fixes output when cleaning libraries --- Makefile | 12 ++++++------ kernel/Makefile | 9 ++++----- libs/liballoc | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index dfae8000..ecc27a5c 100755 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ # Designed by Keeton Feavel & Micah Switzer # Copyright the Panix Contributors (c) 2019 -PROJ_NAME = panix +export PROJ_NAME = panix # Makefile flags # prevent make from showing "entering/leaving directory" messages @@ -233,13 +233,13 @@ todo: .PHONY: clean clean: @printf "$(COLOR_OK)Cleaning objects...$(COLOR_NONE)\n" - $(RM) -r $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) $(PRODUCT)/$(ISOIMG) $(BUILD) + $(RM) -r $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) $(PRODUCT)/$(ISOIMG) @printf "$(COLOR_OK)Cleaning directories...$(COLOR_NONE)\n" - $(RM) -r $(OBJ_DIRS) + $(RM) -r $(BUILD) @printf "$(COLOR_OK)Cleaning libraries...$(COLOR_NONE)\n" - @for dir in $(LIB_DIRS); do \ - printf " - " && \ - $(MAKE) -s -C $$dir clean; \ + @for dir in $(LIB_DIRS); do \ + printf " - " && \ + $(MAKE) -C $$dir clean; \ done @printf "$(COLOR_OK)Cleaning complete.$(COLOR_NONE)\n" diff --git a/kernel/Makefile b/kernel/Makefile index 141c253d..8b163059 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -9,8 +9,6 @@ # Designed by Keeton Feavel & Micah Switzer # Copyright the Panix Contributors (c) 2019 -PROJ_NAME = panix - # ***************************** # * Source Code & Directories * # ***************************** @@ -23,6 +21,10 @@ PRODUCT = ../dist SYSROOT = ../sysroot INCLUDE = $(SYSROOT)/usr/include +# The `| sed "s|^\./||"` command is included to remove the leading +# ./ from all of the paths so that the objects are generated +# properly. Otherwise the object directory is "obj." and not "obj" + # Assembly ATT_SRC = $(shell find . -type f -name "*.s" | sed "s|^\./||") NASM_SRC = $(shell find . -type f -name "*.S" | sed "s|^\./||") @@ -36,9 +38,6 @@ HEADERS = $(CPP_HDR) $(C_HDR) #Libraries LIBS_B = $(addprefix ../, $(LIBS_A)) LIBS = $(addprefix -l:,$(LIBS_B)) -# The `| sed "s|^\./||"` command is included to remove the leading -# ./ from all of the paths so that the objects are generated -# properly. Otherwise the object directory is "obj." and not "obj" # ******************* # * Toolchain Flags * diff --git a/libs/liballoc b/libs/liballoc index 98c2e249..48196099 160000 --- a/libs/liballoc +++ b/libs/liballoc @@ -1 +1 @@ -Subproject commit 98c2e249d431608e3d7d4aca23f41412972de18a +Subproject commit 4819609961e1da7218ccca64875deed759d94848 From f9bd4a49950e18743b0cf84871e5d9a4926c342d Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Tue, 8 Dec 2020 22:42:30 -0500 Subject: [PATCH 104/139] Fixes libraries not being found by kernel Makefile --- Makefile | 55 ++++++++++++++++++++++--------------------------- kernel/Makefile | 7 ++++--- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index ecc27a5c..ec8bb5b9 100755 --- a/Makefile +++ b/Makefile @@ -35,12 +35,9 @@ KERNEL = kernel ISOIMG = $(PROJ_NAME).iso SYMBOLS = $(KERNEL).sym PRODUCT = dist -SYSROOT = sysroot -INCLUDE = $(SYSROOT)/usr/include # Libraries export LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) -export LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") # ******************* # * i686 Toolchains * @@ -62,26 +59,26 @@ export MKGRUB := $(shell command -v grub-mkrescue) # Warning flags # (Disable unused functions warning) -export WARNINGS := \ - -Wall \ - -Werror \ - -Wextra \ - -Winline \ - -Wshadow \ - -Wcast-align \ - -Wno-long-long \ - -Wpointer-arith \ - -Wwrite-strings \ - -Wredundant-decls \ - -Wno-unused-function \ +export WARNINGS := \ + -Wall \ + -Werror \ + -Wextra \ + -Winline \ + -Wshadow \ + -Wcast-align \ + -Wno-long-long \ + -Wpointer-arith \ + -Wwrite-strings \ + -Wredundant-decls \ + -Wno-unused-function \ -Wmissing-declarations # Flags to be added later # -Wconversion # C only warnings -export CWARNINGS := \ - -Wnested-externs \ - -Wstrict-prototypes \ - -Wmissing-prototypes \ +export CWARNINGS := \ + -Wnested-externs \ + -Wstrict-prototypes \ + -Wmissing-prototypes \ # C flags (include directory) export CFLAGS := \ -m32 \ @@ -106,15 +103,15 @@ export CPPFLAGS := \ ${PANIX_CPPFLAGS} \ -D VERSION=\"$(GIT_VERSION)\" # Assembler flags -export ASFLAGS := \ - ${PANIX_ASFLAGS} \ +export ASFLAGS := \ + ${PANIX_ASFLAGS} \ --32 # Linker flags -export LDFLAGS := \ - ${PANIX_LDFLAGS} \ - -m elf_i386 \ - -L. \ - -lgcc +export LDFLAGS := \ + ${PANIX_LDFLAGS} \ + -m elf_i386 \ + -lgcc \ + -L. # ************************ # * Kernel Build Targets * @@ -132,16 +129,14 @@ debug: CXXFLAGS += -DDEBUG -g debug: CFLAGS += -DDEBUG -g debug: $(KERNEL) -# ************************* -# * Kernel Source Objects * -# ************************* - # Kernel (Linked With Libraries) .PHONY: $(KERNEL) $(KERNEL): + # Compile all of the libraries @for dir in $(LIB_DIRS); do \ $(MAKE) -C $$dir $(PROJ_NAME); \ done + # Compile the kernel @$(MAKE) -C $(KERNEL) $(KERNEL) # ******************************** diff --git a/kernel/Makefile b/kernel/Makefile index 8b163059..28412a59 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -18,6 +18,7 @@ BUILD = ../obj KERNEL = kernel SYMBOLS = $(KERNEL).sym PRODUCT = ../dist +LIBRARY = ../libs SYSROOT = ../sysroot INCLUDE = $(SYSROOT)/usr/include @@ -36,8 +37,8 @@ C_HDR = $(shell find $(INCLUDE) -type f -name "*.h" | sed "s|^\./||") CPP_HDR = $(shell find $(INCLUDE) -type f -name "*.hpp" | sed "s|^\./||") HEADERS = $(CPP_HDR) $(C_HDR) #Libraries -LIBS_B = $(addprefix ../, $(LIBS_A)) -LIBS = $(addprefix -l:,$(LIBS_B)) +LIBS_A = $(shell find $(LIBRARY) -type f -name "*.a") +LIBS = $(addprefix -l:, $(LIBS_A)) # ******************* # * Toolchain Flags * @@ -95,7 +96,7 @@ $(BUILD)/%.o: %.S $(KERNEL): $(OBJ) @mkdir -p $(PRODUCT) @printf "$(COLOR_COM)(LD)$(COLOR_NONE)\t$@\n" - $(LD) -o $@ $(OBJ) $(LDFLAGS) + @$(LD) -o $@ $(OBJ) $(LDFLAGS) @mv $(KERNEL) $(PRODUCT)/$(KERNEL) @printf "$(COLOR_COM)(OBJCP)$(COLOR_NONE)\t$@\n" @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) From 704e8da5a1d5e0ee70a9ea42b6b9201c36eee7ce Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 9 Dec 2020 19:33:36 -0500 Subject: [PATCH 105/139] Adds compilation section headers in main Makefile --- Makefile | 6 ++++-- libs/liballoc | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ec8bb5b9..9840953c 100755 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ export GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" export COLOR_COM = \033[0;34m export COLOR_OK = \033[0;32m +export COLOR_INFO = \033[0;93m export COLOR_NONE = \033[m # ***************************** @@ -132,12 +133,13 @@ debug: $(KERNEL) # Kernel (Linked With Libraries) .PHONY: $(KERNEL) $(KERNEL): - # Compile all of the libraries + @printf "$(COLOR_INFO)Making Libs$(COLOR_NONE)\n" @for dir in $(LIB_DIRS); do \ $(MAKE) -C $$dir $(PROJ_NAME); \ done - # Compile the kernel + @printf "$(COLOR_INFO)Making Kernel$(COLOR_NONE)\n" @$(MAKE) -C $(KERNEL) $(KERNEL) + @printf "$(COLOR_INFO)Done!$(COLOR_NONE)\n" # ******************************** # * Kernel Distribution Creation * diff --git a/libs/liballoc b/libs/liballoc index 48196099..2827b08d 160000 --- a/libs/liballoc +++ b/libs/liballoc @@ -1 +1 @@ -Subproject commit 4819609961e1da7218ccca64875deed759d94848 +Subproject commit 2827b08d7be46c7ec8b5dfe25c81b9683eb993f8 From f8cb5c057c17bc0b3c23ef38a8a80b70bf867740 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 9 Dec 2020 20:13:04 -0500 Subject: [PATCH 106/139] Kernel Makefile no longer requires mv --- kernel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 28412a59..e7d537b7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -93,10 +93,10 @@ $(BUILD)/%.o: %.S @printf "$(COLOR_COM)(NASM)$(COLOR_NONE)\t$@\n" @$(NASM) -f elf32 -o $@ $< # Kernel object -$(KERNEL): $(OBJ) +$(KERNEL): $(PRODUCT)/$(KERNEL) +$(PRODUCT)/$(KERNEL): $(OBJ) @mkdir -p $(PRODUCT) @printf "$(COLOR_COM)(LD)$(COLOR_NONE)\t$@\n" @$(LD) -o $@ $(OBJ) $(LDFLAGS) - @mv $(KERNEL) $(PRODUCT)/$(KERNEL) @printf "$(COLOR_COM)(OBJCP)$(COLOR_NONE)\t$@\n" @$(OBJCP) --only-keep-debug $(PRODUCT)/$(KERNEL) $(PRODUCT)/$(SYMBOLS) From 639f25a0ff15646a05660b6ce86e017473381085 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Wed, 9 Dec 2020 22:25:05 -0500 Subject: [PATCH 107/139] Integrates unit test Makefile into main Makefile --- .gitignore | 3 ++- Makefile | 17 +++++++++++++++++ tests/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 8cd864cb..ca441c71 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,10 @@ *.elf .DS_Store -# Ignore build directories +# Ignore build output obj/ dist/ +tests/run_tests # Serial Output com1.txt diff --git a/Makefile b/Makefile index 9840953c..d9ef209f 100755 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ KERNEL = kernel ISOIMG = $(PROJ_NAME).iso SYMBOLS = $(KERNEL).sym PRODUCT = dist +TESTS = tests # Libraries export LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) @@ -141,6 +142,18 @@ $(KERNEL): @$(MAKE) -C $(KERNEL) $(KERNEL) @printf "$(COLOR_INFO)Done!$(COLOR_NONE)\n" +# ********************* +# * Kernel Unit Tests * +# ********************* + +.PHONY: $(TESTS) +$(TESTS): + @$(MAKE) -C $(TESTS) + +.PHONY: test +test: + @$(MAKE) -C $(TESTS) test + # ******************************** # * Kernel Distribution Creation * # ******************************** @@ -240,6 +253,10 @@ clean: done @printf "$(COLOR_OK)Cleaning complete.$(COLOR_NONE)\n" +.PHONY: clean-tests +clean-tests: + @$(MAKE) -C $(TESTS) clean + .PHONY: clean-vm clean-vm: @echo Removing VM diff --git a/tests/Makefile b/tests/Makefile index a1f93c15..f69aaf55 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,50 @@ -CXXFLAGS += -m32 -DTESTING -I../sysroot/usr/include/kernel/ -Wno-write-strings +# ____ _ _____ _ +# | _ \ __ _ _ __ (_)_ __ |_ _|__ ___| |_ ___ +# | |_) / _` | '_ \| \ \/ / | |/ _ \/ __| __/ __| +# | __/ (_| | | | | |> < | | __/\__ \ |_\__ \. +# |_| \__,_|_| |_|_/_/\_\ |_|\___||___/\__|___/ +# +# Compiles the kernel source code located in the kernel folder. -run_tests: *.cpp - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $< ../kernel/lib/bitmap.cpp +# Designed by Keeton Feavel & Micah Switzer +# Copyright the Panix Contributors (c) 2019 + +# ***************************** +# * Source Code & Directories * +# ***************************** + +# Directories & files +KERNEL = kernel +SYSROOT = ../sysroot +INCLUDE = $(SYSROOT)/usr/include + +# Define the compilation flags for the tests. +CXXFLAGS += \ + -Wno-write-strings + +CPPFLAGS += \ + -I$(INCLUDE)/$(KERNEL)/ \ + -DTESTING +# Use the host's copy of GCC instead of the i686 cross compiler +# since it does not have a standard library (if compiled properly) +CXX := $(shell command -v gcc) +# macOS does not support compiling for i386 +# so we only add the -m32 flag for Linux hosts. +UNAME_S := $(shell uname -s) + +run_tests: *.cpp +ifeq ($(UNAME_S), Linux) + CXXFLAGS += -m32 +endif +ifeq ($(UNAME_S), Darwin) + @printf "\n$(COLOR_INFO)WARNING$(COLOR_NONE): Compiling for Darwin (amd64)\n\n" +endif + @$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $< ../$(KERNEL)/lib/bitmap.cpp .PHONY: test test: run_tests - @ ./run_tests + @./run_tests +.PHONY: clean +clean: + @$(RM) run_tests From 9fb40e1cd415bf293ae58cec36a8ec2907b97e1e Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Thu, 10 Dec 2020 23:07:58 -0500 Subject: [PATCH 108/139] Fixes memcmp and strcat --- kernel/lib/string.cpp | 22 +++++++++------------- sysroot/usr/include/kernel/lib/string.hpp | 17 ++++++++--------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/kernel/lib/string.cpp b/kernel/lib/string.cpp index 89a0600f..03abf8bf 100644 --- a/kernel/lib/string.cpp +++ b/kernel/lib/string.cpp @@ -20,15 +20,11 @@ int strlen(const char* s) { return i; } -//TODO: Fix this function. I don't think it works. -char* strcat(const char *s1, const char *s2) { - const size_t len1 = strlen(s1); - const size_t len2 = strlen(s2); - char *result = (char *)malloc(len1 + len2 + 1); // +1 for the null-terminator - // in real code you would check for errors in malloc here - memcpy(result, s1, len1); - memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator - return result; +char* strcat(char *dest, const char *src) { + const size_t len_dest = strlen(dest); + const size_t len_src = strlen(src); + memcpy(dest + len_dest, src, len_src + 1); + return dest; } void strcpy(char* destination, const char* source) { @@ -71,14 +67,14 @@ void* memset(void* bufptr, int value, size_t size) { return bufptr; } -int memcmp(const void* ptr1, const void* ptr2, size_t size) { +int memcmp(const void* ptr1, const void* ptr2, size_t num) { const unsigned char* a = (const unsigned char*) ptr1; const unsigned char* b = (const unsigned char*) ptr2; - for (size_t i = 0; i < size; i++) { + for (size_t i = 0; i < num; i++) { if (a[i] < b[i]) - return -1; + return (int)-i; else if (a[i] > b[i]) - return 1; + return (int)i; } return 0; } diff --git a/sysroot/usr/include/kernel/lib/string.hpp b/sysroot/usr/include/kernel/lib/string.hpp index 8d185983..19258a6b 100644 --- a/sysroot/usr/include/kernel/lib/string.hpp +++ b/sysroot/usr/include/kernel/lib/string.hpp @@ -30,13 +30,13 @@ int strlen(const char* s); */ void strcpy(char* destination, const char* source); /** - * @brief Concatanates string one onto string two. + * @brief Concatanates source onto destination. * - * @param s1 String one - * @param s2 String two - * @return char* Resulting concatenated string + * @param dest Destination + * @param src Source + * @return char* Pointer to destination */ -char* strcat(const char *s1, const char *s2); +char* strcat(char *dest, const char *src); /** * @brief Reverses the inputted string. * @@ -45,11 +45,11 @@ char* strcat(const char *s1, const char *s2); void reverse(char* s); /** * @brief Converts an integer into its ASCII representation. + * (This does not have a standard, ANSI implementation.) * * @param n Number to be converted to ASCII * @param str Buffer to hold result */ -// TODO: Set this to abide by the ASNI C standard function void itoa(int n, char str[]); /** * @brief Sets the number of bytes in memory at ptr to the value. @@ -65,12 +65,11 @@ void* memset(void* bufptr, int value, size_t num); * * @param ptr1 Source pointer * @param ptr2 Destination pointer - * @param size Number of bytes + * @param num Number of bytes * @return int Returns 0 if identical. If negative, pointer A is less than * than pointer B and vice versa for positive. */ -// TODO: Fix the return type to be ANSI compliant -int memcmp(const void* ptr1, const void* ptr2, size_t size); +int memcmp(const void* ptr1, const void* ptr2, size_t num); /** * @brief Moves a given number of bytes from the source to the destination. * From f2d40d8cf527b45103a8e63a8cdd5daa293c2f63 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Thu, 10 Dec 2020 23:08:36 -0500 Subject: [PATCH 109/139] Removes old todos and unused x64 code --- kernel/arch/README.md | 6 ------ kernel/arch/i386/interrupt.s | 4 ++-- kernel/sys/panic.cpp | 16 ---------------- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/kernel/arch/README.md b/kernel/arch/README.md index a5b0b1fe..b88f5dab 100644 --- a/kernel/arch/README.md +++ b/kernel/arch/README.md @@ -3,9 +3,3 @@ A lot of the functions in the kernel folder (basically 100% of them) assume we'r All code that makes this assumption should go into the i386 folder and all code that enables long mode (x64 execution) should go in an x86_64 folder. Likewise, any ARM specific code should go in an armvX folder where X is the ARM processor version. There's still some cleanup to do in terms of moving processor specific code into this folder, but we'll do that eventually. - -## TODO List: -**amd64**: -- [ ] Convert IDT to amd64. There needs to be a new descriptor table moved into arch.hpp [Source](https://wiki.osdev.org/Interrupt_Descriptor_Table#Structure_AMD64) -- [ ] Fix `uint32_t` issue in paging code (ugh...) -`kernel//mem/paging.cpp:143: Error: unsupported instruction 'mov'` \ No newline at end of file diff --git a/kernel/arch/i386/interrupt.s b/kernel/arch/i386/interrupt.s index 11afcf81..6fc02aa8 100644 --- a/kernel/arch/i386/interrupt.s +++ b/kernel/arch/i386/interrupt.s @@ -29,7 +29,7 @@ isr_common_stub: popal addl $8, %esp # Cleans up the pushed error code and pushed ISR number iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP - # TODO: These irets need to be iretq's when in long mode + # These irets need to be iretq's when in long mode # Common IRQ code. Identical to ISR code except for the 'call' # and the 'pop ebx' @@ -54,7 +54,7 @@ irq_common_stub: popal addl $8, %esp iret - # TODO: These irets need to be iretq's when in long mode + # These irets need to be iretq's when in long mode # We don't get information about which interrupt was called # when the handler is run, so we will need to have a different handler diff --git a/kernel/sys/panic.cpp b/kernel/sys/panic.cpp index 513246a8..20384e48 100644 --- a/kernel/sys/panic.cpp +++ b/kernel/sys/panic.cpp @@ -168,22 +168,6 @@ void panic_print_register(registers_t *regs) { regs->ss ); #endif - #if defined(__amd64__) | defined(__x86_64__) - // TODO: Update the panic registers to match amd64. - px_ksprintf( - msg, - "\033[31m DS:\033[0m 0x%08X\n" - "\033[31mRDI:\033[0m 0x%08X \033[31mRSI:\033[0m 0x%08X \033[31mRBP:\033[0m 0x%08X \033[31mRSP:\033[0m 0x%08X\n" - "\033[31mRAX:\033[0m 0x%08X \033[31mRBX:\033[0m 0x%08X \033[31mRCX:\033[0m 0x%08X \033[31mRDX:\033[0m 0x%08X\n" - "\033[31mERR:\033[0m 0x%08X \033[31mRIP:\033[0m 0x%08X \033[31m CS:\033[0m 0x%08X\n" - "\033[31mFLG:\033[0m 0x%08X \033[31m SS:\033[0m 0x%08X\n\n", - regs->ds, - regs->rdi, regs->rsi, regs->rbp, regs->rsp, - regs->rax, regs->rbx, regs->rcx, regs->rdx, - regs->err_code, regs->rip, regs->cs, regs->rflags, - regs->ss - ); - #endif // Print to VGA and serial px_kprintf("%s", msg); px_rs232_print(msg); From 20e9b06bcdf3e2474a06ec01097dd43c5d3ea1af Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Thu, 10 Dec 2020 23:08:52 -0500 Subject: [PATCH 110/139] Removes compiler setting from VSCode workspace --- panix.code-workspace | 1 - 1 file changed, 1 deletion(-) diff --git a/panix.code-workspace b/panix.code-workspace index 2e07bc2e..38bb8179 100644 --- a/panix.code-workspace +++ b/panix.code-workspace @@ -18,7 +18,6 @@ "C_Cpp.clang_format_fallbackStyle": "LLVM", "C_Cpp.default.cppStandard": "c++17", "C_Cpp.default.cStandard": "c17", - "C_Cpp.default.intelliSenseMode": "gcc-x86", "doxdocgen.file.copyrightTag": [ "@copyright Copyright the Panix Contributors (c) {year}" ], From 57c4e7983eb6cb315b831640399941064bfe9355 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Fri, 11 Dec 2020 22:28:52 -0500 Subject: [PATCH 111/139] Fixes missing LibGCC by using reported absolute path --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d9ef209f..94d7b147 100755 --- a/Makefile +++ b/Makefile @@ -39,7 +39,13 @@ PRODUCT = dist TESTS = tests # Libraries +# Okay, time to rant. For *whatever* reason, when I compile and install my +# i686-elf cross compiler, libgcc can never be found. It doesn't matter if +# I'm running macOS, Arch, etc. It always has this issue, so, I decided to +# solve it by just having GCC tell me where it is and then linking against +# that absolute path directly. That way I never have to deal with it again export LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) +export LIB_GCC := $(shell i686-elf-gcc -print-libgcc-file-name) # ******************* # * i686 Toolchains * @@ -111,8 +117,8 @@ export ASFLAGS := \ # Linker flags export LDFLAGS := \ ${PANIX_LDFLAGS} \ + $(LIB_GCC) \ -m elf_i386 \ - -lgcc \ -L. # ************************ From 269194a91dde5dcb791af79ed77c4b6381be57b4 Mon Sep 17 00:00:00 2001 From: James Orson Date: Wed, 16 Dec 2020 16:58:22 -0800 Subject: [PATCH 112/139] Add macros to check mutex validity and acquire a lock --- kernel/lib/mutex.cpp | 49 +++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 1b84a5d1..a6cbe7fe 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -23,13 +23,18 @@ #include #include +#define ACQUIRE_MUTEX_LOCK(mutex) __atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE) + +#define IS_MUTEX_VALID(mutex) { \ + if (mutex == NULL) \ + { \ + errno = EINVAL; \ + return -1; \ + } \ +} + int px_mutex_init(px_mutex_t *mutex) { - // Check if the mutex is valid - if (mutex == NULL) - { - errno = EINVAL; - return -1; - } + IS_MUTEX_VALID(mutex); // Initialize the value to false mutex->locked = false; // Success, return 0 @@ -37,26 +42,16 @@ int px_mutex_init(px_mutex_t *mutex) { } int px_mutex_destroy(px_mutex_t *mutex) { - // Check if the mutex is valid - if (mutex == NULL) - { - errno = EINVAL; - return -1; - } + IS_MUTEX_VALID(mutex); free(mutex); // Success, return 0 return 0; } int px_mutex_lock(px_mutex_t *mutex) { - // Check if the mutex is valid - if (mutex == NULL) - { - errno = EINVAL; - return -1; - } + IS_MUTEX_VALID(mutex); // Check if the mutex is unlocked - while (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) + while (ACQUIRE_MUTEX_LOCK(mutex)) { // Busy wait while trying to get the lock } @@ -65,14 +60,9 @@ int px_mutex_lock(px_mutex_t *mutex) { } int px_mutex_trylock(px_mutex_t *mutex) { - // Check if the mutex is valid - if (mutex == NULL) - { - errno = EINVAL; - return -1; - } + IS_MUTEX_VALID(mutex); // If we cannot immediately acquire the lock then just return an error - if (__atomic_test_and_set(&mutex->locked, __ATOMIC_RELEASE)) + if (ACQUIRE_MUTEX_LOCK(mutex)) { errno = EINVAL; return -1; @@ -82,12 +72,7 @@ int px_mutex_trylock(px_mutex_t *mutex) { } int px_mutex_unlock(px_mutex_t *mutex) { - // Check if the mutex is valid - if (mutex == NULL) - { - errno = EINVAL; - return -1; - } + IS_MUTEX_VALID(mutex); // Clear the lock if it is locked __atomic_clear(&mutex->locked, __ATOMIC_RELEASE); // Success, return 0 From 8235270823edc0def6c9d70d4321d22c02afac92 Mon Sep 17 00:00:00 2001 From: James Orson Date: Wed, 16 Dec 2020 19:33:43 -0800 Subject: [PATCH 113/139] Add semaphore macros --- kernel/lib/semaphore.cpp | 72 +++++++++++++++------------------------- 1 file changed, 27 insertions(+), 45 deletions(-) diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index a119620e..9517cc95 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -23,36 +23,38 @@ #include #include +#define IS_SEMAPHORE_VALID(sem) { \ + if (sem == NULL) \ + { \ + errno = EINVAL; \ + return -1; \ + } \ +} + +#define COMPARE_EXCHANGE(sem, curVal, failure_memorder) __atomic_compare_exchange_n( \ + &sem->count, \ + &curVal, \ + curVal - 1, \ + false, \ + __ATOMIC_RELEASE, \ + failure_memorder \ +) + int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } + IS_SEMAPHORE_VALID(sem); sem->count = value; sem->shared = shared; return 0; } int px_sem_destroy(px_sem_t *sem) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } + IS_SEMAPHORE_VALID(sem); free(sem); return 0; } int px_sem_wait(px_sem_t *sem) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } + IS_SEMAPHORE_VALID(sem); // Used to store the current value of the semaphore for atomic comparison later. uint32_t curVal = sem->count; // Compare the semaphore's current value to the value recorded earlier. @@ -64,18 +66,13 @@ int px_sem_wait(px_sem_t *sem) { curVal = sem->count; } // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. - } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); + } while(!COMPARE_EXCHANGE(sem, curVal, __ATOMIC_RELAXED)); // Return success return 0; } int sem_trywait(px_sem_t *sem) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } + IS_SEMAPHORE_VALID(sem); // Used to store the current value of the semaphore for atomic comparison later. uint32_t curVal = sem->count; // Compare the semaphore's current value to the value recorded earlier. @@ -90,20 +87,15 @@ int sem_trywait(px_sem_t *sem) { return -1; } // We need to fail on an Atomic Acquire Release because it will fail less often (i.e. fewer loop iterations) - } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)); + } while(!COMPARE_EXCHANGE(sem, curVal, __ATOMIC_ACQUIRE)); // To get here the semaphore must not have been locked. return 0; } int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { + IS_SEMAPHORE_VALID(sem); // TODO: Add the timer functionality here. (void)usec; - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } // Used to store the current value of the semaphore for atomic comparison later. uint32_t curVal = sem->count; // Compare the semaphore's current value to the value recorded earlier. @@ -115,29 +107,19 @@ int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { curVal = sem->count; } // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. - } while(!__atomic_compare_exchange_n(&sem->count, &curVal, curVal - 1, false, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)); + } while(!COMPARE_EXCHANGE(sem, curVal, __ATOMIC_ACQUIRE)); // Return success return 0; } int px_sem_post(px_sem_t *sem) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } + IS_SEMAPHORE_VALID(sem); __atomic_fetch_add(&sem->count, 1, __ATOMIC_RELEASE); return 0; } int px_sem_getval(px_sem_t *sem, uint32_t *val) { - // Check if the semaphore is valid - if (sem == NULL) - { - errno = EINVAL; - return -1; - } + IS_SEMAPHORE_VALID(sem); __atomic_load(&sem->count, &val, __ATOMIC_ACQUIRE); return 0; } From faf70855e04cf2e824704207e10a2347c71864d6 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 18 Dec 2020 23:17:54 -0500 Subject: [PATCH 114/139] #168: Adds _init & _fini in crti.s & crtn.s --- Makefile | 52 ++++++++++++++++++++--------------------- kernel/Makefile | 14 ++++++----- kernel/arch/i386/boot.s | 9 ++++++- kernel/arch/i386/crti.s | 16 +++++++++++++ kernel/arch/i386/crtn.s | 10 ++++++++ kernel/main.cpp | 28 ---------------------- 6 files changed, 68 insertions(+), 61 deletions(-) create mode 100644 kernel/arch/i386/crti.s create mode 100644 kernel/arch/i386/crtn.s diff --git a/Makefile b/Makefile index 94d7b147..474da60c 100755 --- a/Makefile +++ b/Makefile @@ -25,6 +25,20 @@ export COLOR_OK = \033[0;32m export COLOR_INFO = \033[0;93m export COLOR_NONE = \033[m +# ******************* +# * i686 Toolchains * +# ******************* + +# Compilers/Assemblers/Linkers +export NASM := $(shell command -v nasm) +export AS := $(shell command -v i686-elf-as) +export AR := $(shell command -v i686-elf-ar) +export CC := $(shell command -v i686-elf-gcc) +export CXX := $(shell command -v i686-elf-g++) +export LD := $(shell command -v i686-elf-ld) +export OBJCP := $(shell command -v i686-elf-objcopy) +export MKGRUB := $(shell command -v grub-mkrescue) + # ***************************** # * Source Code & Directories * # ***************************** @@ -45,21 +59,7 @@ TESTS = tests # solve it by just having GCC tell me where it is and then linking against # that absolute path directly. That way I never have to deal with it again export LIB_DIRS := $(shell find $(LIBRARY) -mindepth 1 -maxdepth 1 -type d) -export LIB_GCC := $(shell i686-elf-gcc -print-libgcc-file-name) - -# ******************* -# * i686 Toolchains * -# ******************* - -# Compilers/Assemblers/Linkers -export NASM := $(shell command -v nasm) -export AS := $(shell command -v i686-elf-as) -export AR := $(shell command -v i686-elf-ar) -export CC := $(shell command -v i686-elf-gcc) -export CXX := $(shell command -v i686-elf-g++) -export LD := $(shell command -v i686-elf-ld) -export OBJCP := $(shell command -v i686-elf-objcopy) -export MKGRUB := $(shell command -v grub-mkrescue) +export LIB_GCC := $(shell $(CC) -print-libgcc-file-name) # ******************* # * Toolchain Flags * @@ -201,6 +201,17 @@ run: $(PRODUCT)/$(KERNEL) -kernel $(PRODUCT)/$(KERNEL) \ $(QEMU_FLAGS) +# Open the connection to qemu and load our kernel-object file with symbols +.PHONY: run-debug +run-debug: $(PRODUCT)/$(KERNEL) + # Start QEMU with debugger + ($(QEMU) \ + -S -s \ + -kernel $< \ + $(QEMU_FLAGS) > /dev/null &) + sleep 1 + wmctrl -xr qemu.Qemu-system-$(QEMU_ARCH) -b add,above + # Create Virtualbox VM .PHONY: vbox-create vbox-create: $(PRODUCT)/$(ISOIMG) @@ -217,17 +228,6 @@ vbox-create: $(PRODUCT)/$(ISOIMG) vbox: vbox-create $(VBOX) startvm --putenv --debug $(VM_NAME) -# Open the connection to qemu and load our kernel-object file with symbols -.PHONY: debugger -debugger: $(PRODUCT)/$(KERNEL) - # Start QEMU with debugger - ($(QEMU) \ - -S -s \ - -kernel $< \ - $(QEMU_FLAGS) > /dev/null &) - sleep 1 - wmctrl -xr qemu.Qemu-system-$(QEMU_ARCH) -b add,above - # **************************** # * Documentation Generation * # **************************** diff --git a/kernel/Makefile b/kernel/Makefile index e7d537b7..9a53faec 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -4,7 +4,7 @@ # | __/ (_| | | | | |> < | . \ __/ | | | | | __/ | # |_| \__,_|_| |_|_/_/\_\ |_|\_\___|_| |_| |_|\___|_| # -# Compiles the kernel source code located in the kernel folder. +# Compiles the kernel source code. # Designed by Keeton Feavel & Micah Switzer # Copyright the Panix Contributors (c) 2019 @@ -56,11 +56,13 @@ LDFLAGS += \ # ************************* # All objects -OBJ_C = $(patsubst %.c, $(BUILD)/%.o, $(C_SRC)) -OBJ_CPP = $(patsubst %.cpp, $(BUILD)/%.o, $(CPP_SRC)) -OBJ_ASM = $(patsubst %.s, $(BUILD)/%.o, $(ATT_SRC)) \ - $(patsubst %.S, $(BUILD)/%.o, $(NASM_SRC)) -OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) +OBJ_C = $(patsubst %.c, $(BUILD)/%.o, $(C_SRC)) +OBJ_CPP = $(patsubst %.cpp, $(BUILD)/%.o, $(CPP_SRC)) +OBJ_ASM = $(patsubst %.s, $(BUILD)/%.o, $(ATT_SRC)) \ + $(patsubst %.S, $(BUILD)/%.o, $(NASM_SRC)) +OBJ_CRTI := $(shell $(CC) -print-file-name=crtbegin.o) +OBJ_CRTN := $(shell $(CC) -print-file-name=crtend.o) +OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) $(OBJ_CRTI) $(OBJ_CRTN) # Object directories, mirroring source OBJ_DIRS = $(addprefix $(BUILD), $(shell find . -type d | sed "s|^\.||")) # Create object file directories diff --git a/kernel/arch/i386/boot.s b/kernel/arch/i386/boot.s index d60adfcc..2fb92d41 100644 --- a/kernel/arch/i386/boot.s +++ b/kernel/arch/i386/boot.s @@ -1,11 +1,14 @@ # make the _start function available to the linker .global _start +# global constructor and destructor calls +.extern _init +.extern _fini + # external reference to our global constructors and kernel main functions # which are defined in our main.cpp file. This allows assembly to call # function in C++ by telling the compiler they exist "somewhere" .extern px_kernel_main -.extern px_call_constructors # minimal panic function that works in most situations .extern early_panic @@ -159,8 +162,12 @@ _start.has_sse: # Set NULL stack frame for trace xor %ebp, %ebp + # Call global constructors + call _init # Enter the high-level kernel. call px_kernel_main + # Call global destructors + call _fini # By this point we should be into the wild world of C++ # So, this should never be called unless the kernel returns diff --git a/kernel/arch/i386/crti.s b/kernel/arch/i386/crti.s new file mode 100644 index 00000000..30dd4ea2 --- /dev/null +++ b/kernel/arch/i386/crti.s @@ -0,0 +1,16 @@ +/* x86 crti.s */ +.section .init +.global _init +.type _init, @function +_init: + push %ebp + movl %esp, %ebp + /* gcc will nicely put the contents of crtbegin.o's .init section here. */ + +.section .fini +.global _fini +.type _fini, @function +_fini: + push %ebp + movl %esp, %ebp + /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ diff --git a/kernel/arch/i386/crtn.s b/kernel/arch/i386/crtn.s new file mode 100644 index 00000000..1da795d6 --- /dev/null +++ b/kernel/arch/i386/crtn.s @@ -0,0 +1,10 @@ +/* x86 crtn.s */ +.section .init + /* gcc will nicely put the contents of crtend.o's .init section here. */ + popl %ebp + ret + +.section .fini + /* gcc will nicely put the contents of crtend.o's .fini section here. */ + popl %ebp + ret diff --git a/kernel/main.cpp b/kernel/main.cpp index c0c45275..cd1b7215 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -36,39 +36,11 @@ #define VERSION "unknown" #endif -extern "C" void px_call_constructors(); extern "C" void __stack_chk_fail(void); extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_magic); void px_kernel_print_splash(); void px_kernel_boot_tone(); -/** - * @brief The global constuctor is a necessary step when using - * global objects which need to be constructed before the main - * function, px_kernel_main() in our case, is ever called. This - * is much more necessary in an object-oriented architecture, - * so it is less of a concern now. Regardless, the OSDev Wiki - * take a *very* different approach to this, so refactoring - * this might be on the eventual todo list. - * - * According to the OSDev Wiki this is only necessary for C++ - * objects. However, it is useful to know that the - * global constructors are "stored in a sorted array of - * function pointers and invoking these is as simple as - * traversing the array and running each element." - * - */ -typedef void (*constructor)(); -extern "C" constructor _CTORS_START; -extern "C" constructor _CTORS_END; -extern "C" void px_call_constructors() { - // For each global object with a constructor starting at start_ctors, - for (constructor* i = &_CTORS_START; i != &_CTORS_END; i++) { - // Get the object and call the constructor manually. - (*i)(); - } -} - /** * @brief This function is the global handler for all * stack protection. GCC will automatically write the From 7335178ee9ae5bdcf8aac095edd0e7526045a56a Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sat, 19 Dec 2020 14:06:41 -0500 Subject: [PATCH 115/139] Correct the link order of crt object files --- kernel/Makefile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 9a53faec..8c436a14 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -56,13 +56,16 @@ LDFLAGS += \ # ************************* # All objects -OBJ_C = $(patsubst %.c, $(BUILD)/%.o, $(C_SRC)) -OBJ_CPP = $(patsubst %.cpp, $(BUILD)/%.o, $(CPP_SRC)) -OBJ_ASM = $(patsubst %.s, $(BUILD)/%.o, $(ATT_SRC)) \ - $(patsubst %.S, $(BUILD)/%.o, $(NASM_SRC)) -OBJ_CRTI := $(shell $(CC) -print-file-name=crtbegin.o) -OBJ_CRTN := $(shell $(CC) -print-file-name=crtend.o) -OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) $(OBJ_CRTI) $(OBJ_CRTN) +OBJ_CRTBEGIN := $(shell $(CC) -print-file-name=crtbegin.o) +OBJ_CRTEND := $(shell $(CC) -print-file-name=crtend.o) +OBJ_CRTI := $(BUILD)/arch/i386/crti.o # hard-coded for now +OBJ_CRTN := $(BUILD)/arch/i386/crtn.o # hard-coded for now +OBJ_C := $(patsubst %.c, $(BUILD)/%.o, $(C_SRC)) +OBJ_CPP := $(patsubst %.cpp, $(BUILD)/%.o, $(CPP_SRC)) +OBJ_ASM_ALL := $(patsubst %.s, $(BUILD)/%.o, $(ATT_SRC)) \ + $(patsubst %.S, $(BUILD)/%.o, $(NASM_SRC)) +OBJ_ASM := $(filter-out $(OBJ_CRTI) $(OBJ_CRTN),$(OBJ_ASM_ALL)) +OBJ := $(OBJ_CRTI) $(OBJ_CRTBEGIN) $(OBJ_CPP) $(OBJ_C) $(OBJ_ASM) $(OBJ_CRTEND) $(OBJ_CRTN) # Object directories, mirroring source OBJ_DIRS = $(addprefix $(BUILD), $(shell find . -type d | sed "s|^\.||")) # Create object file directories From 6aed96b8eed7824a373391b13536e82895010a01 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 12 Dec 2020 14:01:54 -0500 Subject: [PATCH 116/139] Adds mutual exclusion to RS323 IO --- kernel/dev/serial/rs232.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index f1142b30..fc2616b6 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -15,10 +15,13 @@ #include #include #include +#include static px_ring_buff_t* read_buffer = NULL; uint8_t rs_232_line_index; uint16_t rs_232_port_base; +px_mutex_t mutex_data; +px_mutex_t mutex_init; static int px_rs232_received(); static int px_rs232_is_transmit_empty(); @@ -35,13 +38,21 @@ static int px_rs232_is_transmit_empty() { } static char px_rs232_read_char() { + // Gain mutual exclusion + px_mutex_lock(&mutex_data); while (px_rs232_received() == 0); + // Release mutual exclusion + px_mutex_unlock(&mutex_data); return px_read_byte(rs_232_port_base + RS_232_DATA_REG); } static void px_rs232_write_char(char c) { + // Gain mutual exclusion + px_mutex_lock(&mutex_data); while (px_rs232_is_transmit_empty() == 0); px_write_byte(rs_232_port_base + RS_232_DATA_REG, c); + // Release mutual exclusion + px_mutex_unlock(&mutex_data); } void px_rs232_print(const char* str) { @@ -67,6 +78,8 @@ static void px_rs232_callback(registers_t *regs) { } void px_rs232_init(uint16_t com_id) { + // Gain mutual exclusion + px_mutex_lock(&mutex_init); // Register the IRQ callback rs_232_port_base = com_id; uint8_t IRQ = 0x20 + (com_id == RS_232_COM1 ? RS_232_COM1_IRQ : RS_232_COM2_IRQ); @@ -92,15 +105,23 @@ void px_rs232_init(uint16_t com_id) { "/_/ \\__,_/_/ /_/_/_/|_| |___/____/ \n\n\033[0m" "Panix Serial Output Debugger\n\n" ); + // Release mutual exclusion + px_mutex_unlock(&mutex_init); } px_ring_buff_t* px_rs232_init_buffer(int size) { + // Gain mutual exclusion + px_mutex_lock(&mutex_init); // Allocate space for the input buffer read_buffer = (px_ring_buff_t*)malloc(sizeof(px_ring_buff_t)); // Initialize the ring buffer if (px_ring_buffer_init(read_buffer, size) == 0) { + // Release mutual exclusion + px_mutex_unlock(&mutex_init); return read_buffer; } else { + // Release mutual exclusion + px_mutex_unlock(&mutex_init); return NULL; } } @@ -111,16 +132,22 @@ px_ring_buff_t* px_rs232_get_buffer() { } char px_rs232_get_char() { + // Gain mutual exclusion + px_mutex_lock(&mutex_data); // Grab the last byte and convert to a char uint8_t data = 0; if (read_buffer != NULL) { px_ring_buffer_dequeue(read_buffer, &data); } + // Release mutual exclusion + px_mutex_unlock(&mutex_data); return (char)data; } int px_rs232_get_str(char* str, int max) { + // Gain mutual exclusion + px_mutex_lock(&mutex_data); int idx = 0; // Keep reading until the buffer is empty or // a newline is read. @@ -140,15 +167,21 @@ int px_rs232_get_str(char* str, int max) { break; } } + // Release mutual exclusion + px_mutex_unlock(&mutex_data); // Return the string return idx; } int px_rs232_close() { + // Gain mutual exclusion + px_mutex_lock(&mutex_init); int ret = -1; if (read_buffer != NULL) { ret = px_ring_buffer_destroy(read_buffer); read_buffer = NULL; } + // Release mutual exclusion + px_mutex_unlock(&mutex_init); return ret; } From 24bfd12a6811ab225a8937c229baecde5820e5ba Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 12 Dec 2020 14:02:15 -0500 Subject: [PATCH 117/139] Adds mutual exclusion to TTY printing (putchar) --- kernel/lib/putchar.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/lib/putchar.cpp b/kernel/lib/putchar.cpp index 60b86004..a5703c3b 100644 --- a/kernel/lib/putchar.cpp +++ b/kernel/lib/putchar.cpp @@ -11,6 +11,7 @@ #include #include +#include #include static uint16_t ansi_values[8] = { 0 }; @@ -20,14 +21,14 @@ static size_t ansi_values_index = 0; #define CLEAR_VALS() ansi_values_index = 0 #define ESC ('\033') // ANSI states -enum ansi_state { +typedef enum ansi_state { Normal, Esc, Bracket, Value -}; +} ansi_state_t; // State and value storage -ansi_state ansi_state = Normal; +ansi_state_t ansi_state = Normal; uint16_t ansi_val = 0; // Saved cursor positions uint8_t ansi_cursor_x = 0; @@ -39,8 +40,12 @@ uint16_t px_ansi_vga_table[16] = { VGA_LightGreen, VGA_Yellow, VGA_LightBlue, VGA_LightMagenta, VGA_LightCyan, VGA_White }; +// Printing mutual exclusion +px_mutex_t put_mutex; int putchar(char c) { + // Gain mutual exclusion + px_mutex_lock(&put_mutex); // Moved to avoid cross initialization when calling goto error volatile uint16_t* where; uint16_t attrib = (color_back << 4) | (color_fore & 0x0F); @@ -170,5 +175,7 @@ int putchar(char c) { ansi_state = Normal; ansi_val = 0; end: + // Release mutual exclusion + px_mutex_unlock(&put_mutex); return (int)c; } From 80d60e14aac03e511d1ff546865835faa9f42e3d Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sat, 12 Dec 2020 14:02:35 -0500 Subject: [PATCH 118/139] Fixes incorrect mutex documentation --- sysroot/usr/include/kernel/lib/mutex.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index 4055c9bf..383622e1 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -31,16 +31,17 @@ int px_mutex_init(px_mutex_t *mutex); */ int px_mutex_destroy(px_mutex_t *mutex); /** - * @brief Locks a provided mutex. + * @brief Locks a provided mutex. This call will block + * if the mutex is already locked. * * @param mutex Reference mutex * @return int Returns 0 on success and -1 on error. */ int px_mutex_lock(px_mutex_t *mutex); /** - * @brief Waits for a mutex to become unlocked and then - * locks the mutex for use within whatever context this - * is called. + * @brief Attempts to lock a mutex. If the mutex is + * currently locked then the function will return and + * set errno accordingly. * * @param mutex Reference mutex * @return int Returns 0 on success and -1 on error. From 2ca1eb87d948a9e789551dd99ce53a1af8751f90 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 13 Dec 2020 10:15:35 -0500 Subject: [PATCH 119/139] Adds mutual exclusion to get/free page funcs --- kernel/mem/paging.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 1ede2993..78381d96 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #define KADDR_TO_PHYS(addr) ((addr) - KERNEL_BASE) static uint32_t machine_page_count; +static px_mutex_t mutex_paging; #define MEM_BITMAP_SIZE BITMAP_SIZE(ADDRESS_SPACE_SIZE / PAGE_SIZE) @@ -212,6 +214,7 @@ static uint32_t find_next_free_phys_page() { * map in a new page. if you request less than one page, you will get exactly one page */ void* px_get_new_page(uint32_t size) { + px_mutex_lock(&mutex_paging); uint32_t page_count = (size / PAGE_SIZE) + 1; uint32_t free_idx = find_next_free_virt_addr(page_count); if (free_idx == SIZE_T_MAX_VALUE) return NULL; @@ -220,10 +223,12 @@ void* px_get_new_page(uint32_t size) { if (phys_page_idx == SIZE_T_MAX_VALUE) return NULL; px_map_kernel_page(VADDR((uint32_t)i * PAGE_SIZE), phys_page_idx * PAGE_SIZE); } + px_mutex_unlock(&mutex_paging); return (void *)(free_idx * PAGE_SIZE); } void px_free_page(void *page, uint32_t size) { + px_mutex_lock(&mutex_paging); uint32_t page_count = (size / PAGE_SIZE) + 1; uint32_t page_index = (uint32_t)page >> 12; for (uint32_t i = page_index; i < page_index + page_count; i++) { @@ -241,6 +246,7 @@ void px_free_page(void *page, uint32_t size) { // clear that tlb px_invalidate_page(page); } + px_mutex_unlock(&mutex_paging); } bool px_page_is_present(size_t addr) { From 6ced5a733228fe513db648b9db0f8190e7a2584e Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 13 Dec 2020 10:18:10 -0500 Subject: [PATCH 120/139] Removes unnecessary comments/locks --- kernel/dev/serial/rs232.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index fc2616b6..b46f2ea4 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -38,20 +38,16 @@ static int px_rs232_is_transmit_empty() { } static char px_rs232_read_char() { - // Gain mutual exclusion px_mutex_lock(&mutex_data); while (px_rs232_received() == 0); - // Release mutual exclusion px_mutex_unlock(&mutex_data); return px_read_byte(rs_232_port_base + RS_232_DATA_REG); } static void px_rs232_write_char(char c) { - // Gain mutual exclusion px_mutex_lock(&mutex_data); while (px_rs232_is_transmit_empty() == 0); px_write_byte(rs_232_port_base + RS_232_DATA_REG, c); - // Release mutual exclusion px_mutex_unlock(&mutex_data); } @@ -78,8 +74,6 @@ static void px_rs232_callback(registers_t *regs) { } void px_rs232_init(uint16_t com_id) { - // Gain mutual exclusion - px_mutex_lock(&mutex_init); // Register the IRQ callback rs_232_port_base = com_id; uint8_t IRQ = 0x20 + (com_id == RS_232_COM1 ? RS_232_COM1_IRQ : RS_232_COM2_IRQ); @@ -105,22 +99,17 @@ void px_rs232_init(uint16_t com_id) { "/_/ \\__,_/_/ /_/_/_/|_| |___/____/ \n\n\033[0m" "Panix Serial Output Debugger\n\n" ); - // Release mutual exclusion - px_mutex_unlock(&mutex_init); } px_ring_buff_t* px_rs232_init_buffer(int size) { - // Gain mutual exclusion px_mutex_lock(&mutex_init); // Allocate space for the input buffer read_buffer = (px_ring_buff_t*)malloc(sizeof(px_ring_buff_t)); // Initialize the ring buffer if (px_ring_buffer_init(read_buffer, size) == 0) { - // Release mutual exclusion px_mutex_unlock(&mutex_init); return read_buffer; } else { - // Release mutual exclusion px_mutex_unlock(&mutex_init); return NULL; } @@ -132,7 +121,6 @@ px_ring_buff_t* px_rs232_get_buffer() { } char px_rs232_get_char() { - // Gain mutual exclusion px_mutex_lock(&mutex_data); // Grab the last byte and convert to a char uint8_t data = 0; @@ -140,13 +128,11 @@ char px_rs232_get_char() { { px_ring_buffer_dequeue(read_buffer, &data); } - // Release mutual exclusion px_mutex_unlock(&mutex_data); return (char)data; } int px_rs232_get_str(char* str, int max) { - // Gain mutual exclusion px_mutex_lock(&mutex_data); int idx = 0; // Keep reading until the buffer is empty or @@ -167,21 +153,18 @@ int px_rs232_get_str(char* str, int max) { break; } } - // Release mutual exclusion px_mutex_unlock(&mutex_data); // Return the string return idx; } int px_rs232_close() { - // Gain mutual exclusion px_mutex_lock(&mutex_init); int ret = -1; if (read_buffer != NULL) { ret = px_ring_buffer_destroy(read_buffer); read_buffer = NULL; } - // Release mutual exclusion px_mutex_unlock(&mutex_init); return ret; } From e7fe75899fd23fd064669eaf63aa7f9feedc69d9 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Wed, 16 Dec 2020 19:12:11 -0500 Subject: [PATCH 121/139] Adds default constructor to mutex & semaphore --- kernel/mem/liballoc_impl.cpp | 2 +- sysroot/usr/include/kernel/lib/mutex.hpp | 3 +++ sysroot/usr/include/kernel/lib/semaphore.hpp | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/mem/liballoc_impl.cpp b/kernel/mem/liballoc_impl.cpp index db3ef611..ffeb1af3 100644 --- a/kernel/mem/liballoc_impl.cpp +++ b/kernel/mem/liballoc_impl.cpp @@ -3,7 +3,7 @@ #include #include -static px_mutex_t lock = { 0 }; +static px_mutex_t lock; #ifdef __cplusplus extern "C" { diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index 383622e1..c75451e2 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -14,6 +14,9 @@ typedef struct px_mutex { bool locked; + px_mutex() { + locked = false; + }; } px_mutex_t; /** diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index b768fafd..d50bf3a9 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -15,6 +15,10 @@ typedef struct px_semaphore { bool shared; uint32_t count; + px_semaphore() { + shared = false; + count = 0; + } } px_sem_t; /** From 3bdeff4e9b8da7b86529fdf7470d0b4669912476 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Wed, 16 Dec 2020 20:19:04 -0500 Subject: [PATCH 122/139] Moves semaphore & mutex constructors out of header --- kernel/lib/mutex.cpp | 4 ++++ kernel/lib/semaphore.cpp | 5 +++++ sysroot/usr/include/kernel/lib/mutex.hpp | 4 +--- sysroot/usr/include/kernel/lib/semaphore.hpp | 5 +---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index a6cbe7fe..425f570a 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -33,6 +33,10 @@ } \ } +px_mutex::px_mutex() { + locked = false; +}; + int px_mutex_init(px_mutex_t *mutex) { IS_MUTEX_VALID(mutex); // Initialize the value to false diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 9517cc95..795e7d73 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -40,6 +40,11 @@ failure_memorder \ ) +px_semaphore::px_semaphore() { + shared = false; + count = 0; +} + int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { IS_SEMAPHORE_VALID(sem); sem->count = value; diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index c75451e2..8da4ab54 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -14,9 +14,7 @@ typedef struct px_mutex { bool locked; - px_mutex() { - locked = false; - }; + px_mutex(); } px_mutex_t; /** diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index d50bf3a9..177165c5 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -15,10 +15,7 @@ typedef struct px_semaphore { bool shared; uint32_t count; - px_semaphore() { - shared = false; - count = 0; - } + px_semaphore(); } px_sem_t; /** From 3a03093bec68519396452355c86f5b563df29083 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Wed, 16 Dec 2020 22:36:12 -0500 Subject: [PATCH 123/139] Removes extra mutex in RS232 driver --- kernel/dev/serial/rs232.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index b46f2ea4..667769b4 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -20,8 +20,7 @@ static px_ring_buff_t* read_buffer = NULL; uint8_t rs_232_line_index; uint16_t rs_232_port_base; -px_mutex_t mutex_data; -px_mutex_t mutex_init; +px_mutex_t mutex_rs232; static int px_rs232_received(); static int px_rs232_is_transmit_empty(); @@ -38,17 +37,17 @@ static int px_rs232_is_transmit_empty() { } static char px_rs232_read_char() { - px_mutex_lock(&mutex_data); + px_mutex_lock(&mutex_rs232); while (px_rs232_received() == 0); - px_mutex_unlock(&mutex_data); + px_mutex_unlock(&mutex_rs232); return px_read_byte(rs_232_port_base + RS_232_DATA_REG); } static void px_rs232_write_char(char c) { - px_mutex_lock(&mutex_data); + px_mutex_lock(&mutex_rs232); while (px_rs232_is_transmit_empty() == 0); px_write_byte(rs_232_port_base + RS_232_DATA_REG, c); - px_mutex_unlock(&mutex_data); + px_mutex_unlock(&mutex_rs232); } void px_rs232_print(const char* str) { @@ -102,15 +101,15 @@ void px_rs232_init(uint16_t com_id) { } px_ring_buff_t* px_rs232_init_buffer(int size) { - px_mutex_lock(&mutex_init); + px_mutex_lock(&mutex_rs232); // Allocate space for the input buffer read_buffer = (px_ring_buff_t*)malloc(sizeof(px_ring_buff_t)); // Initialize the ring buffer if (px_ring_buffer_init(read_buffer, size) == 0) { - px_mutex_unlock(&mutex_init); + px_mutex_unlock(&mutex_rs232); return read_buffer; } else { - px_mutex_unlock(&mutex_init); + px_mutex_unlock(&mutex_rs232); return NULL; } } @@ -121,19 +120,19 @@ px_ring_buff_t* px_rs232_get_buffer() { } char px_rs232_get_char() { - px_mutex_lock(&mutex_data); + px_mutex_lock(&mutex_rs232); // Grab the last byte and convert to a char uint8_t data = 0; if (read_buffer != NULL) { px_ring_buffer_dequeue(read_buffer, &data); } - px_mutex_unlock(&mutex_data); + px_mutex_unlock(&mutex_rs232); return (char)data; } int px_rs232_get_str(char* str, int max) { - px_mutex_lock(&mutex_data); + px_mutex_lock(&mutex_rs232); int idx = 0; // Keep reading until the buffer is empty or // a newline is read. @@ -153,18 +152,18 @@ int px_rs232_get_str(char* str, int max) { break; } } - px_mutex_unlock(&mutex_data); + px_mutex_unlock(&mutex_rs232); // Return the string return idx; } int px_rs232_close() { - px_mutex_lock(&mutex_init); + px_mutex_lock(&mutex_rs232); int ret = -1; if (read_buffer != NULL) { ret = px_ring_buffer_destroy(read_buffer); read_buffer = NULL; } - px_mutex_unlock(&mutex_init); + px_mutex_unlock(&mutex_rs232); return ret; } From 90a6a4963557ed196718fc543767709b57eaa26d Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Tue, 22 Dec 2020 14:36:39 -0500 Subject: [PATCH 124/139] #174: Replace Include Guards With Pragma Once --- sysroot/usr/include/kernel/arch/arch.hpp | 6 +----- sysroot/usr/include/kernel/arch/i386/gdt.hpp | 5 +---- sysroot/usr/include/kernel/arch/i386/idt.hpp | 5 +---- sysroot/usr/include/kernel/arch/i386/isr.hpp | 6 +----- sysroot/usr/include/kernel/arch/i386/ports.hpp | 5 +---- sysroot/usr/include/kernel/arch/i386/regs.hpp | 6 +----- sysroot/usr/include/kernel/arch/i386/timer.hpp | 6 +----- sysroot/usr/include/kernel/arch/i386/tss.hpp | 6 +----- sysroot/usr/include/kernel/dev/kbd/kbd.hpp | 6 +----- sysroot/usr/include/kernel/dev/kbd/scode.hpp | 6 +----- sysroot/usr/include/kernel/dev/rtc/rtc.hpp | 6 +----- sysroot/usr/include/kernel/dev/serial/rs232.hpp | 1 + sysroot/usr/include/kernel/dev/spkr/spkr.hpp | 6 +----- sysroot/usr/include/kernel/dev/tty/tty.hpp | 5 +---- sysroot/usr/include/kernel/lib/assert.hpp | 5 +---- sysroot/usr/include/kernel/lib/bitmap.hpp | 7 +------ sysroot/usr/include/kernel/lib/ctype.hpp | 6 +----- sysroot/usr/include/kernel/lib/errno.h | 6 +----- sysroot/usr/include/kernel/lib/linked_list.hpp | 6 +----- sysroot/usr/include/kernel/lib/mutex.hpp | 2 +- sysroot/usr/include/kernel/lib/ring_buffer.hpp | 6 +----- sysroot/usr/include/kernel/lib/semaphore.hpp | 1 + sysroot/usr/include/kernel/lib/stdio.hpp | 3 ++- sysroot/usr/include/kernel/lib/string.hpp | 6 +----- sysroot/usr/include/kernel/mem/heap.hpp | 6 +----- sysroot/usr/include/kernel/mem/paging.hpp | 6 +----- sysroot/usr/include/kernel/sys/panic.hpp | 6 +----- sysroot/usr/include/kernel/sys/tasks.hpp | 6 +----- sysroot/usr/include/kernel/sys/trace.hpp | 6 +----- 29 files changed, 30 insertions(+), 123 deletions(-) diff --git a/sysroot/usr/include/kernel/arch/arch.hpp b/sysroot/usr/include/kernel/arch/arch.hpp index de0c94ee..9504fa78 100644 --- a/sysroot/usr/include/kernel/arch/arch.hpp +++ b/sysroot/usr/include/kernel/arch/arch.hpp @@ -8,13 +8,11 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ +#pragma once #include #include -#ifndef PANIX_ARCH_HPP -#define PANIX_ARCH_HPP - const char* px_cpu_get_vendor(); const char* px_cpu_get_model(); @@ -100,5 +98,3 @@ typedef struct registers { /* Include headers for ARM 64 */ #endif /* arm64 */ - -#endif /* PANIX_ARCH_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/gdt.hpp b/sysroot/usr/include/kernel/arch/i386/gdt.hpp index 1d902d15..5e57c021 100644 --- a/sysroot/usr/include/kernel/arch/i386/gdt.hpp +++ b/sysroot/usr/include/kernel/arch/i386/gdt.hpp @@ -9,8 +9,7 @@ * @copyright Copyright Keeton Feavel (c) 2019 * */ -#ifndef PANIX_GLOBAL_DESCRIPTOR_TABLE_HPP -#define PANIX_GLOBAL_DESCRIPTOR_TABLE_HPP +#pragma once #include @@ -92,5 +91,3 @@ typedef struct gdt_ptr gdt_ptr_t; * */ extern void px_gdt_install(); - -#endif /* PANIX_GLOBAL_DESCRIPTOR_TABLE_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/idt.hpp b/sysroot/usr/include/kernel/arch/i386/idt.hpp index c3d87c6a..e3576475 100644 --- a/sysroot/usr/include/kernel/arch/i386/idt.hpp +++ b/sysroot/usr/include/kernel/arch/i386/idt.hpp @@ -9,8 +9,7 @@ * */ -#ifndef PANIX_IDT_HPP -#define PANIX_IDT_HPP +#pragma once #include @@ -63,5 +62,3 @@ void px_idt_set_gate(int n, uint32_t handler); * */ void px_load_idt(); - -#endif /* PANIX_IDT_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/isr.hpp b/sysroot/usr/include/kernel/arch/i386/isr.hpp index d8d08e08..1a30aff8 100644 --- a/sysroot/usr/include/kernel/arch/i386/isr.hpp +++ b/sysroot/usr/include/kernel/arch/i386/isr.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_ISR_HPP -#define PANIX_ISR_HPP +#pragma once #include #include @@ -149,5 +147,3 @@ extern "C" void px_register_interrupt_handler(uint8_t n, isr_t handler); * */ extern "C" void px_irq_handler(registers_t *regs); - -#endif /* PANIX_ISR_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/ports.hpp b/sysroot/usr/include/kernel/arch/i386/ports.hpp index 7e045c6c..352a2270 100644 --- a/sysroot/usr/include/kernel/arch/i386/ports.hpp +++ b/sysroot/usr/include/kernel/arch/i386/ports.hpp @@ -14,8 +14,7 @@ * @copyright Copyright Keeton Feavel (c) 2019 * */ -#ifndef PANIX_PORT_HPP -#define PANIX_PORT_HPP +#pragma once #include @@ -68,5 +67,3 @@ uint32_t px_read_long(uint16_t port); * @param data Long to be written to the port */ void px_write_long(uint16_t port, uint32_t data); - -#endif /* PANIX_PORT_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/regs.hpp b/sysroot/usr/include/kernel/arch/i386/regs.hpp index 6750fae7..c48d2123 100644 --- a/sysroot/usr/include/kernel/arch/i386/regs.hpp +++ b/sysroot/usr/include/kernel/arch/i386/regs.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_X86_REGISTERS_HPP -#define PANIX_X86_REGISTERS_HPP +#pragma once #include @@ -47,5 +45,3 @@ typedef struct px_register_cr3 uint32_t ignored_b : 7; // Ignored uint32_t page_dir : 10; // Page directory address } px_register_cr3_t; - -#endif /* PANIX_X86_REGISTERS_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/timer.hpp b/sysroot/usr/include/kernel/arch/i386/timer.hpp index 6469b69b..d3ac5146 100644 --- a/sysroot/usr/include/kernel/arch/i386/timer.hpp +++ b/sysroot/usr/include/kernel/arch/i386/timer.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_I386_TIMER_HPP -#define PANIX_I386_TIMER_HPP +#pragma once #include @@ -38,5 +36,3 @@ void px_timer_print(); void sleep(uint32_t ms); void px_timer_register_callback(void (*func)()); - -#endif /* PANIX_I386_TIMER_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/arch/i386/tss.hpp b/sysroot/usr/include/kernel/arch/i386/tss.hpp index 1c32d62e..4ef3be08 100644 --- a/sysroot/usr/include/kernel/arch/i386/tss.hpp +++ b/sysroot/usr/include/kernel/arch/i386/tss.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_TASK_STATE_SEGMENT -#define PANIX_TASK_STATE_SEGMENT +#pragma once #include @@ -64,5 +62,3 @@ typedef struct tss_entry { uint16_t trap; uint16_t iomap_base; } __attribute__ ((packed)) tss_entry_t; - -#endif /* PANIX_TASK_STATE_SEGMENT */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/dev/kbd/kbd.hpp b/sysroot/usr/include/kernel/dev/kbd/kbd.hpp index 76248f52..2a820a4c 100644 --- a/sysroot/usr/include/kernel/dev/kbd/kbd.hpp +++ b/sysroot/usr/include/kernel/dev/kbd/kbd.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_KEYBOARD_HPP -#define PANIX_KEYBOARD_HPP +#pragma once #include @@ -37,5 +35,3 @@ extern uint8_t px_kbd_scode_buff[256]; // This index is circular so when we would run // off the end of the array we loop back to 0. extern uint8_t px_kbd_scode_buff_pos; - -#endif /* PANIX_KEYBOARD_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/dev/kbd/scode.hpp b/sysroot/usr/include/kernel/dev/kbd/scode.hpp index 0eb836cf..87b40773 100644 --- a/sysroot/usr/include/kernel/dev/kbd/scode.hpp +++ b/sysroot/usr/include/kernel/dev/kbd/scode.hpp @@ -10,9 +10,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_KEYBOARD_SCANCODES_HPP -#define PANIX_KEYBOARD_SCANCODES_HPP +#pragma once #define PX_SCODE_BACKSPACE 0x0E #define PX_SCODE_ENTER 0x1C @@ -31,5 +29,3 @@ const char px_kbd_usa_ascii[] = { 'b', 'n', 'm', ',', '.', '/', '\0', '*', '\0', ' ' }; - -#endif /* PANIX_KEYBOARD_SCANCODES_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/dev/rtc/rtc.hpp b/sysroot/usr/include/kernel/dev/rtc/rtc.hpp index 2f008ab9..489ca2c7 100644 --- a/sysroot/usr/include/kernel/dev/rtc/rtc.hpp +++ b/sysroot/usr/include/kernel/dev/rtc/rtc.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_RTC_HPP -#define PANIX_RTC_HPP +#pragma once #include @@ -38,5 +36,3 @@ void px_rtc_init(); * */ void px_rtc_print(); - -#endif /* PANIX_RTC_CPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index 993c0d3b..022d1b30 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -9,6 +9,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ +#pragma once #include #include diff --git a/sysroot/usr/include/kernel/dev/spkr/spkr.hpp b/sysroot/usr/include/kernel/dev/spkr/spkr.hpp index 7cc21cb6..8c623aab 100644 --- a/sysroot/usr/include/kernel/dev/spkr/spkr.hpp +++ b/sysroot/usr/include/kernel/dev/spkr/spkr.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_DEVICE_SPKR_HPP -#define PANIX_DEVICE_SPKR_HPP +#pragma once #include @@ -21,5 +19,3 @@ * @param ms Length in milliseconds */ void px_spkr_beep(uint32_t freq, uint32_t ms); - -#endif /* PANIX_DEVICE_SPKR_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/dev/tty/tty.hpp b/sysroot/usr/include/kernel/dev/tty/tty.hpp index 88faa6d8..06b6a2ee 100644 --- a/sysroot/usr/include/kernel/dev/tty/tty.hpp +++ b/sysroot/usr/include/kernel/dev/tty/tty.hpp @@ -13,8 +13,7 @@ * @copyright Copyright Keeton Feavel (c) 2019 * */ -#ifndef PANIX_PX_KPRINT_HPP -#define PANIX_PX_KPRINT_HPP +#pragma once #include #include @@ -115,5 +114,3 @@ void px_tty_reset_defaults(); * @param color Indicator color */ void px_set_indicator(px_tty_vga_color color); - -#endif /* PANIX_px_kprint_HPP */ diff --git a/sysroot/usr/include/kernel/lib/assert.hpp b/sysroot/usr/include/kernel/lib/assert.hpp index 203c6a75..6bcf8e58 100644 --- a/sysroot/usr/include/kernel/lib/assert.hpp +++ b/sysroot/usr/include/kernel/lib/assert.hpp @@ -8,9 +8,8 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ +#pragma once -#ifndef PANIX_ASSERT_HPP -#define PANIX_ASSERT_HPP /** * @brief Creates an assertion which must be held to be true. * If the assertion passes, nothing happens and the kernel @@ -21,5 +20,3 @@ * */ #define assert(x) (!(x) ? (PANIC("Assert failed at ")) : (void)0) - -#endif /* PANIX_ASSERT_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/lib/bitmap.hpp b/sysroot/usr/include/kernel/lib/bitmap.hpp index d057ca44..df7c1d45 100644 --- a/sysroot/usr/include/kernel/lib/bitmap.hpp +++ b/sysroot/usr/include/kernel/lib/bitmap.hpp @@ -8,9 +8,7 @@ * @copyright Copyright Keeton Feavel et al (c) 2020 * */ - -#ifndef PANIX_LIB_BITMAP -#define PANIX_LIB_BITMAP +#pragma once #include @@ -46,6 +44,3 @@ static inline void bitmap_clear_bit(bitmap_t *bitmap, size_t index) { size_t bitmap_find_first_bit_clear(bitmap_t *bitmap, size_t size); size_t bitmap_find_first_range_clear(bitmap_t *bitmap, size_t size, size_t count); - -#endif - diff --git a/sysroot/usr/include/kernel/lib/ctype.hpp b/sysroot/usr/include/kernel/lib/ctype.hpp index 4b657404..0e51b581 100644 --- a/sysroot/usr/include/kernel/lib/ctype.hpp +++ b/sysroot/usr/include/kernel/lib/ctype.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PANIX_CTYPE_HPP -#define PANIX_CTYPE_HPP +#pragma once #include @@ -38,5 +36,3 @@ */ // TODO: Set this to abide by the ASNI C standard function char* toupper(char* str); - -#endif /* PANIX_CTYPE_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/lib/errno.h b/sysroot/usr/include/kernel/lib/errno.h index 06a79aa5..d445d1b8 100644 --- a/sysroot/usr/include/kernel/lib/errno.h +++ b/sysroot/usr/include/kernel/lib/errno.h @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PANIX_LIB_ERRNO_HPP -#define PANIX_LIB_ERRNO_HPP +#pragma once // This is currently not thread safe. // But we also don't have threads, so problem solved. @@ -106,5 +104,3 @@ extern int errno; #define ETXTBSY 79 /* Text file busy. */ #define EWOULDBLOCK 80 /* Operation would block (may be the same value as #define EAGAIN]). */ #define EXDEV 81 /* Cross-device link. */ - -#endif /* PANIX_LIB_ERRNO_HPP */ diff --git a/sysroot/usr/include/kernel/lib/linked_list.hpp b/sysroot/usr/include/kernel/lib/linked_list.hpp index e7c9500d..bf7b9f2a 100644 --- a/sysroot/usr/include/kernel/lib/linked_list.hpp +++ b/sysroot/usr/include/kernel/lib/linked_list.hpp @@ -9,9 +9,7 @@ * Thanks for mrvn on the OSDev Wiki for the implementation: * Linked List Bucket Heap 2013 Goswin von Brederlow */ - -#ifndef PANIX_LIB_LINKED_LIST -#define PANIX_LIB_LINKED_LIST +#pragma once #include #include @@ -120,5 +118,3 @@ DList* dlist_pop(DList **dp); * @param d2 Node to be removed */ void dlist_remove_from(DList **d1p, DList *d2); - -#endif /* PANIX_LIB_LINKED_LIST */ diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index 8da4ab54..d9a8b914 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -8,7 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - +#pragma once #include diff --git a/sysroot/usr/include/kernel/lib/ring_buffer.hpp b/sysroot/usr/include/kernel/lib/ring_buffer.hpp index ea19693a..6ce74f65 100644 --- a/sysroot/usr/include/kernel/lib/ring_buffer.hpp +++ b/sysroot/usr/include/kernel/lib/ring_buffer.hpp @@ -10,9 +10,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PX_RING_BUFFER_HPP -#define PX_RING_BUFFER_HPP +#pragma once #include @@ -96,5 +94,3 @@ int px_ring_buffer_length(px_ring_buff_t* buff); * @return int Buffer capacity in bytes */ int px_ring_buffer_size(px_ring_buff_t* buff); - -#endif /* PX_RING_BUFFER_HPP */ diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index 177165c5..eff6c879 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -8,6 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ +#pragma once #include diff --git a/sysroot/usr/include/kernel/lib/stdio.hpp b/sysroot/usr/include/kernel/lib/stdio.hpp index 94507df0..6fd7aa29 100644 --- a/sysroot/usr/include/kernel/lib/stdio.hpp +++ b/sysroot/usr/include/kernel/lib/stdio.hpp @@ -8,6 +8,7 @@ * @copyright Copyright Keeton Feavel et al (c) 2020 * */ +#pragma once #include #include @@ -74,4 +75,4 @@ int puts(const char *str); * @param ... Sequence of additional arguments * @return int The total number of characters written. */ -int px_debugf(const char* fmt, ...); \ No newline at end of file +int px_debugf(const char* fmt, ...); diff --git a/sysroot/usr/include/kernel/lib/string.hpp b/sysroot/usr/include/kernel/lib/string.hpp index 19258a6b..8a74972c 100644 --- a/sysroot/usr/include/kernel/lib/string.hpp +++ b/sysroot/usr/include/kernel/lib/string.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PANIX_LIB_STRING_HPP -#define PANIX_LIB_STRING_HPP +#pragma once #include #include @@ -88,5 +86,3 @@ void* memmove(void* destination, const void* source, size_t size); * @return void* */ void* memcpy(void* dstptr, const void* srcptr, size_t size); - -#endif /* PANIX_LIB_STRING_HPP */ \ No newline at end of file diff --git a/sysroot/usr/include/kernel/mem/heap.hpp b/sysroot/usr/include/kernel/mem/heap.hpp index 8f1bd2a7..f45643fa 100644 --- a/sysroot/usr/include/kernel/mem/heap.hpp +++ b/sysroot/usr/include/kernel/mem/heap.hpp @@ -12,9 +12,7 @@ * * https://wiki.osdev.org/User:Mrvn/LinkedListBucketHeapImplementation */ - -#ifndef PANIX_MEM_HEAP -#define PANIX_MEM_HEAP +#pragma once #include @@ -65,5 +63,3 @@ extern void *realloc(void *, size_t); extern void *calloc(size_t, size_t); extern void free(void *); } - -#endif /* PANIX_MEM_HEAP */ diff --git a/sysroot/usr/include/kernel/mem/paging.hpp b/sysroot/usr/include/kernel/mem/paging.hpp index 6d50c575..f5bd80a2 100644 --- a/sysroot/usr/include/kernel/mem/paging.hpp +++ b/sysroot/usr/include/kernel/mem/paging.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2019 * */ - -#ifndef PANIX_MEM_PAGING -#define PANIX_MEM_PAGING +#pragma once #include #include @@ -157,5 +155,3 @@ bool px_page_is_present(size_t addr); * @returns the physical address of the current page directory. */ uint32_t px_get_phys_page_dir(); - -#endif /* PANIX_MEM_PAGING */ diff --git a/sysroot/usr/include/kernel/sys/panic.hpp b/sysroot/usr/include/kernel/sys/panic.hpp index b8145efd..e0fab10e 100644 --- a/sysroot/usr/include/kernel/sys/panic.hpp +++ b/sysroot/usr/include/kernel/sys/panic.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PANIX_PANIC_HPP -#define PANIX_PANIC_HPP +#pragma once #include // Data type definitions #include // Architecture specific features @@ -38,5 +36,3 @@ void panic(const char* msg, const char *file, uint32_t line, const char *func); * @param func Function containing error */ void panic(registers_t *regs, const char *file, uint32_t line, const char *func); - -#endif /* PANIX_PANIC_HPP */ diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 6b525bd4..93834fb1 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -8,9 +8,7 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PANIX_TASKS_HPP -#define PANIX_TASKS_HPP +#pragma once #include // Data type definitions #include // Architecture specific features @@ -58,5 +56,3 @@ void px_tasks_unblock(px_task_t *task); void px_tasks_nano_sleep_until(uint64_t time); void px_tasks_nano_sleep(uint64_t time); void px_tasks_exit(void); - -#endif /* PANIX_TASKS_HPP */ diff --git a/sysroot/usr/include/kernel/sys/trace.hpp b/sysroot/usr/include/kernel/sys/trace.hpp index 495f432f..cfdc6151 100644 --- a/sysroot/usr/include/kernel/sys/trace.hpp +++ b/sysroot/usr/include/kernel/sys/trace.hpp @@ -8,12 +8,8 @@ * @copyright Copyright the Panix Contributors (c) 2020 * */ - -#ifndef PANIX_SYS_TRACE_HPP -#define PANIX_SYS_TRACE_HPP +#pragma once #include void px_stack_trace(size_t max); - -#endif /* PANIX_SYS_TRACE_HPP */ \ No newline at end of file From 3fc8ce382d298189f2bb55db640ab71d26ea003d Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Tue, 22 Dec 2020 16:18:13 -0500 Subject: [PATCH 125/139] #178: Update Panix Copyright Message --- kernel/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/main.cpp b/kernel/main.cpp index cd1b7215..742d6a00 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -127,7 +127,7 @@ void px_kernel_print_splash() { px_kprintf( "\033[93mWelcome to Panix\n" "Developed by graduates and undergraduates of Cedarville University.\n" - "Copyright Keeton Feavel et al (c) %i. All rights reserved.\n\033[0m", + "Copyright the Panix Contributors (c) %i. All rights reserved.\n\033[0m", (\ ((__DATE__)[7] - '0') * 1000 + \ ((__DATE__)[8] - '0') * 100 + \ From 2c7d2bea016853dd3d96c4553372f6297714cea9 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Fri, 30 Oct 2020 22:10:23 -0400 Subject: [PATCH 126/139] Began working on multitasking mutual exclusion --- kernel/lib/mutex.cpp | 4 +- kernel/lib/semaphore.cpp | 1 + sysroot/usr/include/kernel/lib/mutex.hpp | 8 ++- sysroot/usr/include/kernel/lib/semaphore.hpp | 2 + sysroot/usr/include/kernel/sys/tasks.hpp | 74 ++++++++++++++++++-- 5 files changed, 81 insertions(+), 8 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 425f570a..994613f4 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -41,6 +41,7 @@ int px_mutex_init(px_mutex_t *mutex) { IS_MUTEX_VALID(mutex); // Initialize the value to false mutex->locked = false; + TASKS_SYNC_INIT(&mutex->task_sync); // Success, return 0 return 0; } @@ -57,7 +58,8 @@ int px_mutex_lock(px_mutex_t *mutex) { // Check if the mutex is unlocked while (ACQUIRE_MUTEX_LOCK(mutex)) { - // Busy wait while trying to get the lock + // Block the current kernel task + px_tasks_block_current(TASK_BLOCKED); } // Success, return 0 return 0; diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 795e7d73..3edf55e0 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -49,6 +49,7 @@ int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { IS_SEMAPHORE_VALID(sem); sem->count = value; sem->shared = shared; + TASKS_SYNC_INIT(&sem->task_sync); return 0; } diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index d9a8b914..5d223f73 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -11,22 +11,24 @@ #pragma once #include +#include typedef struct px_mutex { bool locked; + px_tasks_sync_t task_sync; px_mutex(); } px_mutex_t; /** * @brief Initializes a mutex for further use. - * + * * @param mutex Reference mutex * @return int Returns 0 on success and -1 on error. */ int px_mutex_init(px_mutex_t *mutex); /** * @brief Destroys a mutex and removes it from memory. - * + * * @param mutex Reference mutex * @return int Returns 0 on success and -1 on error. */ @@ -50,7 +52,7 @@ int px_mutex_lock(px_mutex_t *mutex); int px_mutex_trylock(px_mutex_t *mutex); /** * @brief Unlocks a mutex for others to use. - * + * * @param mutex Reference mutex * @return int Returns 0 on success and -1 on error. */ diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index eff6c879..8335acf2 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -11,11 +11,13 @@ #pragma once #include +#include typedef struct px_semaphore { bool shared; uint32_t count; + px_tasks_sync_t task_sync; px_semaphore(); } px_sem_t; diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 93834fb1..377f693f 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -10,13 +10,14 @@ */ #pragma once -#include // Data type definitions +#include // Data type definitions #include // Architecture specific features #include #define TIME_SLICE_SIZE (1 * 1000 * 1000ULL) -enum px_task_state { +enum px_task_state +{ TASK_RUNNING = 0, TASK_READY = 1, TASK_SLEEPING, @@ -26,7 +27,6 @@ enum px_task_state { }; typedef struct px_task px_task_t; - struct px_task { uintptr_t stack_top; @@ -37,22 +37,88 @@ struct px_task uint64_t wakeup_time; }; +extern px_task_t *px_current_task; + typedef struct px_tasklist { px_task_t *head; px_task_t *tail; } px_tasklist_t; +#define MAX_TASKS_QUEUED 8 +typedef struct px_tasks_sync +{ + px_task_t* possessor; + uint16_t queued_head; + uint16_t queued_tail; + px_task_t *queued[MAX_TASKS_QUEUED]; +} px_tasks_sync_t; -extern px_task_t *px_current_task; +#define TASKS_SYNC_INIT(sync) \ + (sync)->possessor = NULL; \ + (sync)->queued_head = 0; \ + (sync)->queued_tail = 0 +/** + * @brief Initializes the kernel task manager. + * + */ void px_tasks_init(); +/** + * @brief Switches to a provided task. + * + * @param task Pointer to the task struct + */ extern "C" void px_tasks_switch_to(px_task_t *task); +/** + * @brief Creates a new kernel task with a provided entry point, register storage struct, + * and task state struct. If the storage parameter is provided, the px_task_t struct + * provided will be written to. If NULL is passed as the storage parameter, a pointer + * to a allocated task will be returned. + * + * @param entry Task function entry point + * @param storage Task stack structure (if NULL, a pointer to the task is returned) + * @param state Task state structure + * @return px_task_t* Pointer to the created kernel task + */ px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state); +/** + * @brief Tell the kernel task scheduler to schedule all of the added tasks. + * + */ void px_tasks_schedule(); +/** + * @brief Returns the lifetime of the current task (in nanoseconds). + * + * @return uint64_t Task lifetime (in nanoseconds) + */ uint64_t px_tasks_get_self_time(); +/** + * @brief Blocks the current task. + * + * @param reason + */ void px_tasks_block_current(px_task_state reason); +/** + * @brief Unblocks the current task. + * + * @param task + */ void px_tasks_unblock(px_task_t *task); +/** + * @brief Sleeps until the provided absolute time (in nanoseconds). + * + * @param time Absolute time to sleep until (in nanoseconds since boot) + */ void px_tasks_nano_sleep_until(uint64_t time); +/** + * @brief Sleep for a given period of time (in nanoseconds). + * + * @param time Nanoseconds to sleep + */ void px_tasks_nano_sleep(uint64_t time); +/** + * @brief Exits the current task. + * + */ void px_tasks_exit(void); From 631bef8e68f542c27f8c5fbb13ca524fe6a8090d Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Sun, 20 Dec 2020 16:38:35 -0500 Subject: [PATCH 127/139] Make mutexes task-aware And other task improvements --- kernel/lib/mutex.cpp | 11 ++-- kernel/lib/semaphore.cpp | 2 +- kernel/sys/tasks.cpp | 64 +++++++++++++++++++++--- sysroot/usr/include/kernel/sys/tasks.hpp | 30 ++++++++--- 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 994613f4..1e9f88dd 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -41,7 +41,7 @@ int px_mutex_init(px_mutex_t *mutex) { IS_MUTEX_VALID(mutex); // Initialize the value to false mutex->locked = false; - TASKS_SYNC_INIT(&mutex->task_sync); + px_tasks_sync_init(&mutex->task_sync); // Success, return 0 return 0; } @@ -59,8 +59,10 @@ int px_mutex_lock(px_mutex_t *mutex) { while (ACQUIRE_MUTEX_LOCK(mutex)) { // Block the current kernel task - px_tasks_block_current(TASK_BLOCKED); + TASK_ONLY px_tasks_sync_block(&mutex->task_sync); } + // aquire the sync structure + TASK_ONLY px_tasks_sync_aquire(&mutex->task_sync); // Success, return 0 return 0; } @@ -79,8 +81,11 @@ int px_mutex_trylock(px_mutex_t *mutex) { int px_mutex_unlock(px_mutex_t *mutex) { IS_MUTEX_VALID(mutex); - // Clear the lock if it is locked + // Release the lock if it is locked + TASK_ONLY px_tasks_sync_release(&mutex->task_sync); + // Clear the lock __atomic_clear(&mutex->locked, __ATOMIC_RELEASE); + TASK_ONLY px_tasks_sync_unblock(&mutex->task_sync); // Success, return 0 return 0; } diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 3edf55e0..9c5f61df 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -49,7 +49,7 @@ int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { IS_SEMAPHORE_VALID(sem); sem->count = value; sem->shared = shared; - TASKS_SYNC_INIT(&sem->task_sync); + px_tasks_sync_init(&sem->task_sync); return 0; } diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 53c22ad9..88a40bfc 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -107,10 +107,14 @@ void px_tasks_init() // just say that this task hasn't spent any time running yet .time_used = 0, // Set wakeup time to 0 to make compiler happy - .wakeup_time = 0 + .wakeup_time = 0, + // name + .name = "[main]", + // this is not backed by dynamic memory + .alloc = ALLOC_STATIC, }; // create a task for the cleaner and set it's state to "paused" - (void) px_tasks_new(_cleaner_task_impl, &_cleaner_task, TASK_PAUSED); + (void) px_tasks_new(_cleaner_task_impl, &_cleaner_task, TASK_PAUSED, "[cleaner]"); _cleaner_task.state = TASK_PAUSED; // update the timer variables _last_time = _get_cpu_time_ns(); @@ -216,7 +220,7 @@ static px_task_t *_px_tasks_dequeue_ready() return _dequeue_task(&px_tasks_ready); } -px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state) +px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state, const char *name) { px_task_t *new_task = storage; if (storage == NULL) { @@ -251,6 +255,8 @@ px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state s new_task->next_task = NULL; new_task->state = state; new_task->time_used = 0; + new_task->name = name; + new_task->alloc = storage == NULL ? ALLOC_STATIC : ALLOC_DYNAMIC; if (state == TASK_READY) { _px_tasks_enqueue_ready(new_task); } @@ -424,10 +430,10 @@ void px_tasks_nano_sleep(uint64_t time) void px_tasks_exit() { - char str[32]; + char str[64]; // userspace cleanup can happen here - px_ksprintf(str, "task 0x%08x exiting.\n", (uint32_t)px_current_task); + px_ksprintf(str, "task \"%s\" (0x%08x) exiting\n", px_current_task->name, (uint32_t)px_current_task); px_rs232_print(str); _aquire_scheduler_lock(); @@ -449,19 +455,19 @@ static void _clean_stopped_task(px_task_t *task) px_free_page((void *)page, PAGE_SIZE - 1); // somehow determine if the task was dynamically allocated or not // just assume statically allocated tasks will never exit (bad idea) - free(task); + if (task->alloc == ALLOC_DYNAMIC) free(task); } static void _cleaner_task_impl() { - char str[32]; + char str[64]; for (;;) { px_task_t *task; _aquire_scheduler_lock(); while (px_tasks_stopped.head != NULL) { task = _dequeue_stopped(); - px_ksprintf(str, "cleaning up task 0x%08x.\n", (uint32_t)task); + px_ksprintf(str, "cleaning up task %s (0x%08x)\n", task->name ? task->name : "N/A", (uint32_t)task); px_rs232_print(str); _clean_stopped_task(task); } @@ -472,3 +478,45 @@ static void _cleaner_task_impl() px_tasks_block_current(TASK_PAUSED); } } + +void px_tasks_sync_block(px_tasks_sync_t *ts) +{ + _aquire_scheduler_lock(); + // push the current task to the waiting queue + _enqueue_task(&ts->waiting, px_current_task); + _release_scheduler_lock(); + // now block until the mutex is freed + px_tasks_block_current(TASK_BLOCKED); +} + +void px_tasks_sync_unblock(px_tasks_sync_t *ts) +{ + _aquire_scheduler_lock(); + // iterate all tasks that were blocked and unblock them + px_task_t *task = ts->waiting.head; + px_task_t *pre = NULL; + if (task == NULL) { + // no other tasks were blocked + goto exit; + } + do { + _remove_task(&ts->waiting, task, pre); + _wakeup(task); + pre = task; + task = task->next_task; + } while (task != NULL); + // we woke up some tasks + _schedule(); +exit: + _release_scheduler_lock(); +} + +void px_tasks_sync_aquire(px_tasks_sync_t *ts) +{ + ts->possessor = px_current_task; +} + +void px_tasks_sync_release(px_tasks_sync_t *ts) +{ + ts->possessor = NULL; +} diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index 377f693f..eb5bf1cf 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -26,6 +26,8 @@ enum px_task_state TASK_PAUSED }; +enum px_task_alloc { ALLOC_STATIC, ALLOC_DYNAMIC }; + typedef struct px_task px_task_t; struct px_task { @@ -35,10 +37,14 @@ struct px_task px_task_state state; uint64_t time_used; uint64_t wakeup_time; + const char *name; + px_task_alloc alloc; }; extern px_task_t *px_current_task; +#define TASK_ONLY if (px_current_task != NULL) + typedef struct px_tasklist { px_task_t *head; @@ -49,15 +55,15 @@ typedef struct px_tasklist typedef struct px_tasks_sync { px_task_t* possessor; - uint16_t queued_head; - uint16_t queued_tail; - px_task_t *queued[MAX_TASKS_QUEUED]; + px_tasklist_t waiting; } px_tasks_sync_t; -#define TASKS_SYNC_INIT(sync) \ - (sync)->possessor = NULL; \ - (sync)->queued_head = 0; \ - (sync)->queued_tail = 0 +static inline void px_tasks_sync_init(px_tasks_sync_t *ts) { + *ts = { + .possessor = NULL, + .waiting = { }, + }; +} /** * @brief Initializes the kernel task manager. @@ -81,7 +87,7 @@ extern "C" void px_tasks_switch_to(px_task_t *task); * @param state Task state structure * @return px_task_t* Pointer to the created kernel task */ -px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state); +px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state state, const char *name); /** * @brief Tell the kernel task scheduler to schedule all of the added tasks. * @@ -122,3 +128,11 @@ void px_tasks_nano_sleep(uint64_t time); * */ void px_tasks_exit(void); + +void px_tasks_sync_block(px_tasks_sync_t *tsc); + +void px_tasks_sync_unblock(px_tasks_sync_t *tsc); + +void px_tasks_sync_aquire(px_tasks_sync_t *tsc); + +void px_tasks_sync_release(px_tasks_sync_t *tsc); From 8fed8ac235496a60ad3a21a52210a6ed95e2d042 Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 20 Dec 2020 20:56:49 -0500 Subject: [PATCH 128/139] #146: Fix deadlock in tasking --- kernel/sys/tasks.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 88a40bfc..e59e1294 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -376,19 +376,23 @@ static void _on_timer() px_task_t *pre = NULL; px_task_t *task = px_tasks_sleeping.head; + px_task_t *next; bool need_schedule = false; uint64_t time = _get_cpu_time_ns(); uint64_t time_delta; while (task != NULL) { + next = task->next_task; if (time >= task->wakeup_time) { //px_rs232_print("timer: waking sleeping task\n"); _remove_task(&px_tasks_sleeping, task, pre); _wakeup(task); + task->next_task = NULL; need_schedule = true; + } else { + pre = task; } - pre = task; - task = task->next_task; + task = next; } if (_time_slice_remaining != 0) { @@ -443,9 +447,10 @@ void px_tasks_exit() // the ordering of these two should really be reversed // but the scheduler currently isn't very smart px_tasks_unblock(&_cleaner_task); - px_tasks_block_current(TASK_STOPPED); _release_scheduler_lock(); + + px_tasks_block_current(TASK_STOPPED); } static void _clean_stopped_task(px_task_t *task) @@ -494,17 +499,19 @@ void px_tasks_sync_unblock(px_tasks_sync_t *ts) _aquire_scheduler_lock(); // iterate all tasks that were blocked and unblock them px_task_t *task = ts->waiting.head; - px_task_t *pre = NULL; + px_task_t *next = NULL; if (task == NULL) { // no other tasks were blocked goto exit; } do { - _remove_task(&ts->waiting, task, pre); + next = task->next_task; _wakeup(task); - pre = task; - task = task->next_task; + task->next_task = NULL; + task = next; } while (task != NULL); + ts->waiting.head = NULL; + ts->waiting.tail = NULL; // we woke up some tasks _schedule(); exit: From 30baac43052291498cfbbd8024ab20ac258e33ce Mon Sep 17 00:00:00 2001 From: "Keeton T. Feavel" Date: Sun, 20 Dec 2020 20:57:16 -0500 Subject: [PATCH 129/139] Fix potential deadlock on printf error --- kernel/lib/putchar.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/lib/putchar.cpp b/kernel/lib/putchar.cpp index a5703c3b..568a5901 100644 --- a/kernel/lib/putchar.cpp +++ b/kernel/lib/putchar.cpp @@ -170,6 +170,8 @@ int putchar(char c) { // Return to normal ansi_state = Normal; ansi_val = 0; + // Release mutual exclusion + px_mutex_unlock(&put_mutex); return EOF; normal: ansi_state = Normal; From 81401722b10a753874fd63bcae062e56d72e9cab Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Fri, 25 Dec 2020 12:23:27 -0500 Subject: [PATCH 130/139] Make task scheduling deferable --- kernel/sys/tasks.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index e59e1294..6847882e 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -29,6 +29,7 @@ static void _enqueue_task(px_tasklist_t *, px_task *); static px_task_t *_dequeue_task(px_tasklist_t *); static void _cleaner_task_impl(void); +static void _schedule(void); extern "C" void _px_tasks_enqueue_ready(px_task_t *task); void px_tasks_update_time(); void _wakeup(px_task_t *task); @@ -55,16 +56,26 @@ static uint64_t _last_time = 0; static uint64_t _time_slice_remaining = 0; static uint64_t _last_timer_time = 0; static size_t _scheduler_lock = 0; +static size_t _scheduler_postpone_count = 0; +static bool _scheduler_postponed = false; static uint64_t _instr_per_ns; static void _aquire_scheduler_lock() { asm volatile("cli"); + _scheduler_postpone_count++; _scheduler_lock++; } static void _release_scheduler_lock() { + _scheduler_postpone_count--; + if (_scheduler_postpone_count == 0) { + if (_scheduler_postponed) { + _scheduler_postponed = false; + _schedule(); + } + } _scheduler_lock--; if (_scheduler_lock == 0) { asm volatile("sti"); @@ -277,6 +288,11 @@ void px_tasks_update_time() static void _schedule() { + if (_scheduler_postpone_count != 0) { + // don't schedule if there's more work to be done + _scheduler_postponed = true; + return; + } if (px_current_task == NULL) { // we are currently idling and will schedule at a later time return; From ff0949ee995cbddc1f1354f96b561531d265423f Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 28 Dec 2020 09:59:45 -0500 Subject: [PATCH 131/139] Finish task-aware synchronization * Fix deferred scheduling * Fix semaphore initialization * Add printf to rs232 code * Make coarser locks for printf functions * Add debug-only prints to scheduling logic --- kernel/dev/serial/rs232.cpp | 37 ++++- kernel/lib/mutex.cpp | 8 +- kernel/lib/printf.cpp | 21 ++- kernel/lib/putchar.cpp | 18 ++- kernel/lib/semaphore.cpp | 9 +- kernel/mem/liballoc_impl.cpp | 2 +- kernel/mem/paging.cpp | 2 +- kernel/sys/tasks.cpp | 144 +++++++++++++----- .../usr/include/kernel/dev/serial/rs232.hpp | 5 + sysroot/usr/include/kernel/lib/mutex.hpp | 2 +- sysroot/usr/include/kernel/lib/semaphore.hpp | 2 +- sysroot/usr/include/kernel/lib/stdio.hpp | 7 + sysroot/usr/include/kernel/sys/tasks.hpp | 11 +- 13 files changed, 184 insertions(+), 84 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 667769b4..58fc8501 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -16,11 +16,13 @@ #include #include #include +#include +#include static px_ring_buff_t* read_buffer = NULL; uint8_t rs_232_line_index; uint16_t rs_232_port_base; -px_mutex_t mutex_rs232; +px_mutex_t mutex_rs232("rs232"); static int px_rs232_received(); static int px_rs232_is_transmit_empty(); @@ -43,17 +45,44 @@ static char px_rs232_read_char() { return px_read_byte(rs_232_port_base + RS_232_DATA_REG); } -static void px_rs232_write_char(char c) { - px_mutex_lock(&mutex_rs232); +static inline void px_rs232_write_char(char c) { while (px_rs232_is_transmit_empty() == 0); px_write_byte(rs_232_port_base + RS_232_DATA_REG, c); - px_mutex_unlock(&mutex_rs232); +} + +static int vprintf_helper(unsigned c, void **ptr) +{ + (void) ptr; + px_rs232_write_char((char)c); + return 0; +} + +int px_rs232_vprintf(const char* fmt, va_list args) +{ + int retval; + //px_mutex_lock(&mutex_rs232); + retval = px_do_printf(fmt, args, vprintf_helper, NULL); + //px_mutex_unlock(&mutex_rs232); + return retval; +} + +int px_rs232_printf(const char *format, ...) +{ + va_list args; + int ret_val; + + va_start(args, format); + ret_val = px_rs232_vprintf(format, args); + va_end(args); + return ret_val; } void px_rs232_print(const char* str) { + //px_mutex_lock(&mutex_rs232); for (int i = 0; str[i] != 0; i++) { px_rs232_write_char(str[i]); } + //px_mutex_unlock(&mutex_rs232); } static void px_rs232_callback(registers_t *regs) { diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 1e9f88dd..5bf16b39 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -33,8 +33,8 @@ } \ } -px_mutex::px_mutex() { - locked = false; +px_mutex::px_mutex(const char *name) : locked(false) { + task_sync.dbg_name = name; }; int px_mutex_init(px_mutex_t *mutex) { @@ -61,8 +61,6 @@ int px_mutex_lock(px_mutex_t *mutex) { // Block the current kernel task TASK_ONLY px_tasks_sync_block(&mutex->task_sync); } - // aquire the sync structure - TASK_ONLY px_tasks_sync_aquire(&mutex->task_sync); // Success, return 0 return 0; } @@ -81,8 +79,6 @@ int px_mutex_trylock(px_mutex_t *mutex) { int px_mutex_unlock(px_mutex_t *mutex) { IS_MUTEX_VALID(mutex); - // Release the lock if it is locked - TASK_ONLY px_tasks_sync_release(&mutex->task_sync); // Clear the lock __atomic_clear(&mutex->locked, __ATOMIC_RELEASE); TASK_ONLY px_tasks_sync_unblock(&mutex->task_sync); diff --git a/kernel/lib/printf.cpp b/kernel/lib/printf.cpp index c677e9e6..f8f66e6e 100644 --- a/kernel/lib/printf.cpp +++ b/kernel/lib/printf.cpp @@ -91,19 +91,13 @@ Using & for division here, so STACK_WIDTH must be a power of 2. */ 2^32-1 in base 8 has 11 digits (add 5 for trailing NUL and for slop) */ #define PR_BUFLEN 16 -typedef int (*fnptr_t)(unsigned c, void** helper); - -/* Function declarations */ -int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr); -int vprintf_help(unsigned c, void** ptr); - /***************************************************************************** -name: do_printf +name: px_do_printf action: minimal subfunction for ?printf, calls function 'fn' with arg 'ptr' for each character to be output returns:total number of characters output *****************************************************************************/ -int do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr) +int px_do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr) { unsigned char state, radix, *where, buf[PR_BUFLEN]; unsigned flags, actual_wd, count, given_wd; @@ -323,7 +317,7 @@ int px_kvsprintf(char* buf, const char* fmt, va_list args) { int ret_val; - ret_val = do_printf(fmt, args, vsprintf_help, (void*)buf); + ret_val = px_do_printf(fmt, args, vsprintf_help, (void*)buf); buf[ret_val] = '\0'; return ret_val; } @@ -341,17 +335,20 @@ int px_ksprintf(char* buf, const char* fmt, ...) } /***************************************************************************** *****************************************************************************/ -int vprintf_help(unsigned c, void** ptr) +static int vprintf_help(unsigned c, void** ptr) { (void)ptr; - putchar((char)c); + putchar_unlocked((char)c); return 0; } /***************************************************************************** *****************************************************************************/ int px_kvprintf(const char* fmt, va_list args) { - return do_printf(fmt, args, vprintf_help, NULL); + px_mutex_lock(&put_mutex); + int retval = px_do_printf(fmt, args, vprintf_help, NULL); + px_mutex_unlock(&put_mutex); + return retval; } /***************************************************************************** *****************************************************************************/ diff --git a/kernel/lib/putchar.cpp b/kernel/lib/putchar.cpp index 568a5901..289659de 100644 --- a/kernel/lib/putchar.cpp +++ b/kernel/lib/putchar.cpp @@ -41,11 +41,21 @@ uint16_t px_ansi_vga_table[16] = { VGA_LightCyan, VGA_White }; // Printing mutual exclusion -px_mutex_t put_mutex; +px_mutex_t put_mutex("putc"); -int putchar(char c) { +int putchar(char c) +{ + int retval; // Gain mutual exclusion px_mutex_lock(&put_mutex); + retval = putchar_unlocked(c); + // Release mutual exclusion + px_mutex_unlock(&put_mutex); + return retval; +} + +int putchar_unlocked(char c) { + // Moved to avoid cross initialization when calling goto error volatile uint16_t* where; uint16_t attrib = (color_back << 4) | (color_fore & 0x0F); @@ -170,14 +180,10 @@ int putchar(char c) { // Return to normal ansi_state = Normal; ansi_val = 0; - // Release mutual exclusion - px_mutex_unlock(&put_mutex); return EOF; normal: ansi_state = Normal; ansi_val = 0; end: - // Release mutual exclusion - px_mutex_unlock(&put_mutex); return (int)c; } diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 9c5f61df..6029346d 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -40,10 +40,7 @@ failure_memorder \ ) -px_semaphore::px_semaphore() { - shared = false; - count = 0; -} +px_semaphore::px_semaphore(int c, const char *name) : shared(false), count(c) { task_sync.dbg_name = name; } int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { IS_SEMAPHORE_VALID(sem); @@ -69,6 +66,7 @@ int px_sem_wait(px_sem_t *sem) { { while (curVal == 0) { + TASK_ONLY px_tasks_sync_block(&sem->task_sync); curVal = sem->count; } // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster. @@ -121,11 +119,12 @@ int sem_timedwait(px_sem_t *sem, const uint32_t *usec) { int px_sem_post(px_sem_t *sem) { IS_SEMAPHORE_VALID(sem); __atomic_fetch_add(&sem->count, 1, __ATOMIC_RELEASE); + TASK_ONLY px_tasks_sync_unblock(&sem->task_sync); return 0; } int px_sem_getval(px_sem_t *sem, uint32_t *val) { IS_SEMAPHORE_VALID(sem); - __atomic_load(&sem->count, &val, __ATOMIC_ACQUIRE); + __atomic_load(&sem->count, val, __ATOMIC_ACQUIRE); return 0; } diff --git a/kernel/mem/liballoc_impl.cpp b/kernel/mem/liballoc_impl.cpp index ffeb1af3..41cc33b4 100644 --- a/kernel/mem/liballoc_impl.cpp +++ b/kernel/mem/liballoc_impl.cpp @@ -3,7 +3,7 @@ #include #include -static px_mutex_t lock; +static px_mutex_t lock("alloc"); #ifdef __cplusplus extern "C" { diff --git a/kernel/mem/paging.cpp b/kernel/mem/paging.cpp index 78381d96..5f404257 100644 --- a/kernel/mem/paging.cpp +++ b/kernel/mem/paging.cpp @@ -21,7 +21,7 @@ #define KADDR_TO_PHYS(addr) ((addr) - KERNEL_BASE) static uint32_t machine_page_count; -static px_mutex_t mutex_paging; +static px_mutex_t mutex_paging("paging"); #define MEM_BITMAP_SIZE BITMAP_SIZE(ADDRESS_SPACE_SIZE / PAGE_SIZE) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 6847882e..7d471c33 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -50,6 +50,26 @@ px_tasklist_t px_tasks_ready = { /* Zero */ }; NAMED_TASKLIST(sleeping); NAMED_TASKLIST(stopped); +// map between task state and the list it is in +static px_tasklist_t *_state_lists[TASK_STATE_COUNT] = { + [TASK_RUNNING] = NULL, // not in a list + [TASK_READY] = &px_tasks_ready, + [TASK_SLEEPING] = &px_tasks_sleeping, + [TASK_BLOCKED] = NULL, // in a list specific to the blocking primitive + [TASK_STOPPED] = &px_tasks_stopped, + [TASK_PAUSED] = NULL, // not in a list +}; + +// map between task state and its name +static const char *_state_names[TASK_STATE_COUNT] = { + [TASK_RUNNING] = "RUNNING", + [TASK_READY] = "READY", + [TASK_SLEEPING] = "SLEEPING", + [TASK_BLOCKED] = "BLOCKED", + [TASK_STOPPED] = "STOPPED", + [TASK_PAUSED] = "PAUSED", +}; + static uint64_t _idle_time = 0; static uint64_t _idle_start = 0; static uint64_t _last_time = 0; @@ -98,6 +118,39 @@ static inline uint64_t _get_cpu_time_ns() return (__rdtsc()) / _instr_per_ns; } +static void _print_task(const px_task_t *task) +{ + px_rs232_printf("%s is %s\n", task->name, _state_names[task->state]); +} + +#ifdef DEBUG +#define TASK_ACTION(action, task) do { px_rs232_print(action " "); _print_task(task); } while(0) +#else +#define TASK_ACTION(action, task) +#endif + +static void _print_tasklist(const char *name, const px_tasklist_t *list) +{ + px_task_t *task = list->head; + px_rs232_printf("%s:\n", name); + while (task != NULL) { + _print_task(task); + task = task->next; + } +} + +static void _print_tasklist(const px_task_t *task) +{ + const px_tasklist_t *list = _state_lists[task->state]; + const char *state_name = _state_names[task->state]; + if (list == NULL) { + px_rs232_printf("no tasklist available for %s tasks.\n", state_name); + return; + } + + _print_tasklist(state_name, list); +} + static void _on_timer(); void px_tasks_init() @@ -112,7 +165,7 @@ void px_tasks_init() // this will be the same for kernel tasks .page_dir = px_get_phys_page_dir(), // this is a linked list with only this task - .next_task = NULL, + .next = NULL, // this task is currently running .state = TASK_RUNNING, // just say that this task hasn't spent any time running yet @@ -124,6 +177,7 @@ void px_tasks_init() // this is not backed by dynamic memory .alloc = ALLOC_STATIC, }; + TASK_ACTION("create task", this_task); // create a task for the cleaner and set it's state to "paused" (void) px_tasks_new(_cleaner_task_impl, &_cleaner_task, TASK_PAUSED, "[cleaner]"); _cleaner_task.state = TASK_PAUSED; @@ -143,7 +197,11 @@ static void _task_starting() // it is run in the context of the new task // the task before this caused the scheduler to lock - _release_scheduler_lock(); + // so we must unlock here + _scheduler_lock--; + if (_scheduler_lock == 0) { + asm volatile("sti"); + } } static void _task_stopping() @@ -172,9 +230,10 @@ static void _enqueue_task(px_tasklist_t *list, px_task *task) } if (list->tail != NULL) { // the current last task's next pointer will be this task - list->tail->next_task = task; + list->tail->next = task; } // and now this task becomes the last task + task->next = NULL; list->tail = task; } @@ -188,26 +247,27 @@ static px_task_t *_dequeue_task(px_tasklist_t *list) // the head of the list is the next item task = list->head; // the new head is the next task - list->head = task->next_task; + list->head = task->next; + // so null its previous pointer if (list->head == NULL) { // if there are no more items in the list, then // the last item in the list will also be null list->tail = NULL; } - // it doesn't make sense to have a next_task when it's not in a list - task->next_task = NULL; + // it doesn't make sense to have a next when it's not in a list + task->next = NULL; return task; } static void _remove_task(px_tasklist_t *list, px_task_t *task, px_task_t *previous) { // if this is true, something's not right... - if (previous != NULL && previous->next_task != task) { + if (previous != NULL && previous->next != task) { PANIC("Bogus arguments to _remove_task.\n"); } // update the head if necessary if (list->head == task) { - list->head = task->next_task; + list->head = task->next; } // update the tail if necessary if (list->tail == task) { @@ -215,10 +275,10 @@ static void _remove_task(px_tasklist_t *list, px_task_t *task, px_task_t *previo } // update the previous task if necessary if (previous != NULL) { - previous->next_task = task->next_task; + previous->next = task->next; } // it's not in any list anymore, so clear its next pointer - task->next_task = NULL; + task->next = NULL; } extern "C" void _px_tasks_enqueue_ready(px_task_t *task) @@ -263,7 +323,7 @@ px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state s _px_stack_push_word(&stack_pointer, 0); new_task->stack_top = (uintptr_t)stack_pointer; new_task->page_dir = px_get_phys_page_dir(); - new_task->next_task = NULL; + new_task->next = NULL; new_task->state = state; new_task->time_used = 0; new_task->name = name; @@ -271,6 +331,7 @@ px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state s if (state == TASK_READY) { _px_tasks_enqueue_ready(new_task); } + TASK_ACTION("create task", new_task); return new_task; } @@ -338,6 +399,10 @@ static void _schedule() } // reset the time slice because a new task is being scheduled _time_slice_remaining = TIME_SLICE_SIZE; +#ifdef DEBUG + px_rs232_print("switching to "); + _print_task(task); +#endif // reset the last "timer time" since the time slice was reset _last_timer_time = _get_cpu_time_ns(); // switch to the task @@ -364,6 +429,7 @@ void px_tasks_block_current(px_task_state reason) { _aquire_scheduler_lock(); px_current_task->state = reason; + TASK_ACTION("block", px_current_task); _schedule(); _release_scheduler_lock(); } @@ -371,11 +437,9 @@ void px_tasks_block_current(px_task_state reason) void px_tasks_unblock(px_task_t *task) { _aquire_scheduler_lock(); - if (px_tasks_ready.head == NULL) { - px_tasks_switch_to(task); - } else { - _px_tasks_enqueue_ready(task); - } + task->state = TASK_READY; + TASK_ACTION("unblock", task); + _px_tasks_enqueue_ready(task); _release_scheduler_lock(); } @@ -384,6 +448,7 @@ void _wakeup(px_task_t *task) task->state = TASK_READY; task->wakeup_time = (0ULL - 1); _px_tasks_enqueue_ready(task); + TASK_ACTION("wakeup", task); } static void _on_timer() @@ -398,12 +463,12 @@ static void _on_timer() uint64_t time_delta; while (task != NULL) { - next = task->next_task; + next = task->next; if (time >= task->wakeup_time) { //px_rs232_print("timer: waking sleeping task\n"); _remove_task(&px_tasks_sleeping, task, pre); _wakeup(task); - task->next_task = NULL; + task->next = NULL; need_schedule = true; } else { pre = task; @@ -439,6 +504,7 @@ void px_tasks_nano_sleep_until(uint64_t time) px_current_task->state = TASK_SLEEPING; px_current_task->wakeup_time = time; _enqueue_sleeping(px_current_task); + TASK_ACTION("sleep", px_current_task); _schedule(); _release_scheduler_lock(); } @@ -450,11 +516,8 @@ void px_tasks_nano_sleep(uint64_t time) void px_tasks_exit() { - char str[64]; - // userspace cleanup can happen here - px_ksprintf(str, "task \"%s\" (0x%08x) exiting\n", px_current_task->name, (uint32_t)px_current_task); - px_rs232_print(str); + px_rs232_printf("task \"%s\" (0x%08x) exiting\n", px_current_task->name, (uint32_t)px_current_task); _aquire_scheduler_lock(); // all scheduling-specific operations must happen here @@ -462,11 +525,11 @@ void px_tasks_exit() // the ordering of these two should really be reversed // but the scheduler currently isn't very smart + px_tasks_block_current(TASK_STOPPED); + px_tasks_unblock(&_cleaner_task); _release_scheduler_lock(); - - px_tasks_block_current(TASK_STOPPED); } static void _clean_stopped_task(px_task_t *task) @@ -481,38 +544,47 @@ static void _clean_stopped_task(px_task_t *task) static void _cleaner_task_impl() { - char str[64]; for (;;) { px_task_t *task; _aquire_scheduler_lock(); while (px_tasks_stopped.head != NULL) { task = _dequeue_stopped(); - px_ksprintf(str, "cleaning up task %s (0x%08x)\n", task->name ? task->name : "N/A", (uint32_t)task); - px_rs232_print(str); + px_rs232_printf("cleaning up task %s (0x%08x)\n", task->name ? task->name : "N/A", (uint32_t)task); _clean_stopped_task(task); } - _release_scheduler_lock(); // a schedule occuring at this point would be okay // it just needs to occur before the loop repeats px_tasks_block_current(TASK_PAUSED); + + _release_scheduler_lock(); } } void px_tasks_sync_block(px_tasks_sync_t *ts) { _aquire_scheduler_lock(); +#ifdef DEBUG + if (ts->dbg_name != NULL) { + px_rs232_printf("blocking %s\n", ts->dbg_name); + } +#endif // push the current task to the waiting queue _enqueue_task(&ts->waiting, px_current_task); - _release_scheduler_lock(); // now block until the mutex is freed px_tasks_block_current(TASK_BLOCKED); + _release_scheduler_lock(); } void px_tasks_sync_unblock(px_tasks_sync_t *ts) { _aquire_scheduler_lock(); +#ifdef DEBUG + if (ts->dbg_name != NULL) { + px_rs232_printf("unblocking %s\n", ts->dbg_name); + } +#endif // iterate all tasks that were blocked and unblock them px_task_t *task = ts->waiting.head; px_task_t *next = NULL; @@ -521,9 +593,9 @@ void px_tasks_sync_unblock(px_tasks_sync_t *ts) goto exit; } do { - next = task->next_task; + next = task->next; _wakeup(task); - task->next_task = NULL; + task->next = NULL; task = next; } while (task != NULL); ts->waiting.head = NULL; @@ -533,13 +605,3 @@ void px_tasks_sync_unblock(px_tasks_sync_t *ts) exit: _release_scheduler_lock(); } - -void px_tasks_sync_aquire(px_tasks_sync_t *ts) -{ - ts->possessor = px_current_task; -} - -void px_tasks_sync_release(px_tasks_sync_t *ts) -{ - ts->possessor = NULL; -} diff --git a/sysroot/usr/include/kernel/dev/serial/rs232.hpp b/sysroot/usr/include/kernel/dev/serial/rs232.hpp index 022d1b30..852d84e6 100644 --- a/sysroot/usr/include/kernel/dev/serial/rs232.hpp +++ b/sysroot/usr/include/kernel/dev/serial/rs232.hpp @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include @@ -92,3 +93,7 @@ int px_rs232_get_str(char* str, int max); * is set appropriately. */ int px_rs232_close(); + +int px_rs232_vprintf(const char* fmt, va_list args); + +int px_rs232_printf(const char *format, ...); diff --git a/sysroot/usr/include/kernel/lib/mutex.hpp b/sysroot/usr/include/kernel/lib/mutex.hpp index 5d223f73..25aa721d 100644 --- a/sysroot/usr/include/kernel/lib/mutex.hpp +++ b/sysroot/usr/include/kernel/lib/mutex.hpp @@ -16,7 +16,7 @@ typedef struct px_mutex { bool locked; px_tasks_sync_t task_sync; - px_mutex(); + px_mutex(const char *name = nullptr); } px_mutex_t; /** diff --git a/sysroot/usr/include/kernel/lib/semaphore.hpp b/sysroot/usr/include/kernel/lib/semaphore.hpp index 8335acf2..600229a3 100644 --- a/sysroot/usr/include/kernel/lib/semaphore.hpp +++ b/sysroot/usr/include/kernel/lib/semaphore.hpp @@ -18,7 +18,7 @@ typedef struct px_semaphore bool shared; uint32_t count; px_tasks_sync_t task_sync; - px_semaphore(); + px_semaphore(int count, const char *name = nullptr); } px_sem_t; /** diff --git a/sysroot/usr/include/kernel/lib/stdio.hpp b/sysroot/usr/include/kernel/lib/stdio.hpp index 6fd7aa29..3c0e16aa 100644 --- a/sysroot/usr/include/kernel/lib/stdio.hpp +++ b/sysroot/usr/include/kernel/lib/stdio.hpp @@ -12,11 +12,16 @@ #include #include +#include #ifndef EOF #define EOF (-1) #endif +typedef int (*fnptr_t)(unsigned c, void** helper); + +int px_do_printf(const char* fmt, va_list args, fnptr_t fn, void* ptr); + /** * @brief Sends formatted output to a string using an argument list. * @@ -61,6 +66,8 @@ int px_kprintf(const char* fmt, ...); * @param c Character to be printed. */ int putchar(char c); +int putchar_unlocked(char c); +extern px_mutex_t put_mutex; /** * @brief Prints a given string to the kernel display. * diff --git a/sysroot/usr/include/kernel/sys/tasks.hpp b/sysroot/usr/include/kernel/sys/tasks.hpp index eb5bf1cf..3b068c64 100644 --- a/sysroot/usr/include/kernel/sys/tasks.hpp +++ b/sysroot/usr/include/kernel/sys/tasks.hpp @@ -23,7 +23,8 @@ enum px_task_state TASK_SLEEPING, TASK_BLOCKED, TASK_STOPPED, - TASK_PAUSED + TASK_PAUSED, + TASK_STATE_COUNT }; enum px_task_alloc { ALLOC_STATIC, ALLOC_DYNAMIC }; @@ -33,7 +34,7 @@ struct px_task { uintptr_t stack_top; uintptr_t page_dir; - px_task_t *next_task; + px_task_t *next; px_task_state state; uint64_t time_used; uint64_t wakeup_time; @@ -55,12 +56,14 @@ typedef struct px_tasklist typedef struct px_tasks_sync { px_task_t* possessor; + const char *dbg_name; px_tasklist_t waiting; } px_tasks_sync_t; static inline void px_tasks_sync_init(px_tasks_sync_t *ts) { *ts = { .possessor = NULL, + .dbg_name = NULL, .waiting = { }, }; } @@ -132,7 +135,3 @@ void px_tasks_exit(void); void px_tasks_sync_block(px_tasks_sync_t *tsc); void px_tasks_sync_unblock(px_tasks_sync_t *tsc); - -void px_tasks_sync_aquire(px_tasks_sync_t *tsc); - -void px_tasks_sync_release(px_tasks_sync_t *tsc); From 73a487e9ddb38bf39d64a476272e6f7d7628a8bc Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 28 Dec 2020 12:09:37 -0500 Subject: [PATCH 132/139] Address code review comments --- kernel/dev/serial/rs232.cpp | 4 ---- kernel/lib/mutex.cpp | 4 +++- kernel/lib/putchar.cpp | 1 - kernel/lib/semaphore.cpp | 6 +++++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/dev/serial/rs232.cpp b/kernel/dev/serial/rs232.cpp index 58fc8501..f67bc252 100644 --- a/kernel/dev/serial/rs232.cpp +++ b/kernel/dev/serial/rs232.cpp @@ -60,9 +60,7 @@ static int vprintf_helper(unsigned c, void **ptr) int px_rs232_vprintf(const char* fmt, va_list args) { int retval; - //px_mutex_lock(&mutex_rs232); retval = px_do_printf(fmt, args, vprintf_helper, NULL); - //px_mutex_unlock(&mutex_rs232); return retval; } @@ -78,11 +76,9 @@ int px_rs232_printf(const char *format, ...) } void px_rs232_print(const char* str) { - //px_mutex_lock(&mutex_rs232); for (int i = 0; str[i] != 0; i++) { px_rs232_write_char(str[i]); } - //px_mutex_unlock(&mutex_rs232); } static void px_rs232_callback(registers_t *regs) { diff --git a/kernel/lib/mutex.cpp b/kernel/lib/mutex.cpp index 5bf16b39..f04f1cdc 100644 --- a/kernel/lib/mutex.cpp +++ b/kernel/lib/mutex.cpp @@ -33,7 +33,9 @@ } \ } -px_mutex::px_mutex(const char *name) : locked(false) { +px_mutex::px_mutex(const char *name) + : locked(false) +{ task_sync.dbg_name = name; }; diff --git a/kernel/lib/putchar.cpp b/kernel/lib/putchar.cpp index 289659de..7963028d 100644 --- a/kernel/lib/putchar.cpp +++ b/kernel/lib/putchar.cpp @@ -55,7 +55,6 @@ int putchar(char c) } int putchar_unlocked(char c) { - // Moved to avoid cross initialization when calling goto error volatile uint16_t* where; uint16_t attrib = (color_back << 4) | (color_fore & 0x0F); diff --git a/kernel/lib/semaphore.cpp b/kernel/lib/semaphore.cpp index 6029346d..b19600ef 100644 --- a/kernel/lib/semaphore.cpp +++ b/kernel/lib/semaphore.cpp @@ -40,7 +40,11 @@ failure_memorder \ ) -px_semaphore::px_semaphore(int c, const char *name) : shared(false), count(c) { task_sync.dbg_name = name; } +px_semaphore::px_semaphore(int c, const char *name) + : shared(false), count(c) +{ + task_sync.dbg_name = name; +} int px_sem_init(px_sem_t *sem, bool shared, uint32_t value) { IS_SEMAPHORE_VALID(sem); From fd9a3e49a71f8f7ebeef44583b6a4b8ea1588b0c Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Mon, 28 Dec 2020 12:42:43 -0500 Subject: [PATCH 133/139] Update putchar_unlocked comments --- kernel/lib/printf.cpp | 1 + kernel/lib/putchar.cpp | 5 +++-- sysroot/usr/include/kernel/lib/stdio.hpp | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/lib/printf.cpp b/kernel/lib/printf.cpp index f8f66e6e..dc74ed9d 100644 --- a/kernel/lib/printf.cpp +++ b/kernel/lib/printf.cpp @@ -338,6 +338,7 @@ int px_ksprintf(char* buf, const char* fmt, ...) static int vprintf_help(unsigned c, void** ptr) { (void)ptr; + // we use the unlocked putchar here becaus we lock at the printf level putchar_unlocked((char)c); return 0; } diff --git a/kernel/lib/putchar.cpp b/kernel/lib/putchar.cpp index 7963028d..ae5cc73d 100644 --- a/kernel/lib/putchar.cpp +++ b/kernel/lib/putchar.cpp @@ -46,10 +46,11 @@ px_mutex_t put_mutex("putc"); int putchar(char c) { int retval; - // Gain mutual exclusion + // must lock when writing to the screen px_mutex_lock(&put_mutex); + // call the unlocked implementation of putchar retval = putchar_unlocked(c); - // Release mutual exclusion + // release the screen to be used by other tasks px_mutex_unlock(&put_mutex); return retval; } diff --git a/sysroot/usr/include/kernel/lib/stdio.hpp b/sysroot/usr/include/kernel/lib/stdio.hpp index 3c0e16aa..6b67c208 100644 --- a/sysroot/usr/include/kernel/lib/stdio.hpp +++ b/sysroot/usr/include/kernel/lib/stdio.hpp @@ -66,6 +66,14 @@ int px_kprintf(const char* fmt, ...); * @param c Character to be printed. */ int putchar(char c); +/** + * @brief Prints a single character to the screen without locking the screen mutex + * + * Callers of this function *must* manually lock and unlock `put_mutex` when utilizing + * this function to draw to the screen. + * + * @param c the chraracter to be printed. + */ int putchar_unlocked(char c); extern px_mutex_t put_mutex; /** From 91a4088f7a07ddc10f62adbe3b622893c54df88c Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Mon, 28 Dec 2020 23:25:47 -0500 Subject: [PATCH 134/139] #185: Set Panix Version in Makefile --- Makefile | 11 +++++++++-- kernel/main.cpp | 16 +++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 474da60c..7fc7679b 100755 --- a/Makefile +++ b/Makefile @@ -14,7 +14,11 @@ export PROJ_NAME = panix # Makefile flags # prevent make from showing "entering/leaving directory" messages export MAKEFLAGS += --no-print-directory -export GIT_VERSION := "$(shell git describe --abbrev=8 --dirty --always --tags)" +# Panix Version +export GIT_COMMIT := "$(shell git describe --abbrev=8 --dirty --always --tags)" +export VER_MAJOR := "0" +export VER_MINOR := "3" +export VER_PATCH := "0" # ****************************** # * Compiler Output Formatting * @@ -109,7 +113,10 @@ export CXXFLAGS := \ # C / C++ pre-processor flags export CPPFLAGS := \ ${PANIX_CPPFLAGS} \ - -D VERSION=\"$(GIT_VERSION)\" + -D COMMIT=\"$(GIT_COMMIT)\" \ + -D VER_MAJOR=\"$(VER_MAJOR)\" \ + -D VER_MINOR=\"$(VER_MINOR)\" \ + -D VER_PATCH=\"$(VER_PATCH)\" # Assembler flags export ASFLAGS := \ ${PANIX_ASFLAGS} \ diff --git a/kernel/main.cpp b/kernel/main.cpp index 742d6a00..0991e0b8 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -27,13 +27,19 @@ // Used as a magic number for stack smashing protection #if UINT32_MAX == UINTPTR_MAX -#define STACK_CHK_GUARD 0xDEADC0DE + #define STACK_CHK_GUARD 0xDEADC0DE #else -#define STACK_CHK_GUARD 0xBADBADBADBADBAD1 + #define STACK_CHK_GUARD 0xBADBADBADBADBAD1 #endif // Define the Git commit version if not declared by compiler -#ifndef VERSION -#define VERSION "unknown" +#ifndef COMMIT + #define COMMIT "unknown" +#endif +// Assume that if major isn't set none of them are +#ifndef VER_MAJOR + #define VER_MAJOR '0' + #define VER_MINOR '0' + #define VER_PATCH '0' #endif extern "C" void __stack_chk_fail(void); @@ -135,7 +141,7 @@ void px_kernel_print_splash() { ((__DATE__)[10] - '0') * 1 \ ) ); - px_kprintf("Commit %s built on %s at %s.\n\n", VERSION, __DATE__, __TIME__); + px_kprintf("Commit %s (v%s.%s.%s) built on %s at %s.\n\n", COMMIT, VER_MAJOR, VER_MINOR, VER_PATCH, __DATE__, __TIME__); } void px_kernel_boot_tone() { From fd8b1833f5e67300ba9e85f761c05c3cd72b6067 Mon Sep 17 00:00:00 2001 From: Keeton Feavel Date: Tue, 29 Dec 2020 17:30:58 -0500 Subject: [PATCH 135/139] #185: Bump version number to 0.4.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7fc7679b..45494e95 100755 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ export MAKEFLAGS += --no-print-directory # Panix Version export GIT_COMMIT := "$(shell git describe --abbrev=8 --dirty --always --tags)" export VER_MAJOR := "0" -export VER_MINOR := "3" +export VER_MINOR := "4" export VER_PATCH := "0" # ****************************** From 7acca092ae407710df94199130d1ba9d06ccb16a Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Wed, 30 Dec 2020 09:14:00 -0500 Subject: [PATCH 136/139] Fix putchar * Fix save/restore cursor code * Add carriage return capability * Remove debug string from mutex --- kernel/lib/putchar.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/lib/putchar.cpp b/kernel/lib/putchar.cpp index ae5cc73d..31efea5a 100644 --- a/kernel/lib/putchar.cpp +++ b/kernel/lib/putchar.cpp @@ -41,7 +41,7 @@ uint16_t px_ansi_vga_table[16] = { VGA_LightCyan, VGA_White }; // Printing mutual exclusion -px_mutex_t put_mutex("putc"); +px_mutex_t put_mutex; int putchar(char c) { @@ -78,12 +78,12 @@ int putchar_unlocked(char c) { else if (c == 's') { // Save cursor position attribute ansi_cursor_x = tty_coords_x; ansi_cursor_y = tty_coords_y; - goto end; + goto normal; } else if (c == 'u') { // Restore cursor position attribute tty_coords_x = ansi_cursor_x; tty_coords_y = ansi_cursor_y; - goto end; + goto normal; } break; case Value: @@ -151,6 +151,10 @@ int putchar_unlocked(char c) { tty_coords_x = 0; tty_coords_y++; break; + // Carriage return + case '\r': + tty_coords_x = 0; + break; // Anything else default: where = x86_bios_vga_mem + (tty_coords_y * X86_TTY_WIDTH + tty_coords_x); From 9a36bc786ad6907ff2d39feea6dc2be5df8a1fe2 Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Wed, 30 Dec 2020 09:16:00 -0500 Subject: [PATCH 137/139] Make the spinner lock to the bottom of the screen --- kernel/main.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/kernel/main.cpp b/kernel/main.cpp index 742d6a00..f28342c4 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -99,25 +99,12 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma // Keep the kernel alive. px_kprintf("\n"); int i = 0; + const char spinnay[] = { '|', '/', '-', '\\' }; while (true) { // Display a spinner to know that we're still running. - switch (i) { - case 0: - px_kprintf("\b|"); - break; - case 1: - px_kprintf("\b/"); - break; - case 2: - px_kprintf("\b-"); - break; - case 3: - px_kprintf("\b\\"); - i = -1; - break; - } + px_kprintf("\e[s\e[24;0f%c\e[u", spinnay[i]); + i = (i + 1) % sizeof(spinnay); asm volatile("hlt"); - i++; } PANIC("Kernel terminated unexpectedly!"); } From d121c44968850ad51e857e970629872c5a0e566a Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Wed, 30 Dec 2020 09:17:38 -0500 Subject: [PATCH 138/139] Fix task cleanup bug The dynamic alloc and static alloc cases were reversed in px_tasks_new --- kernel/sys/tasks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sys/tasks.cpp b/kernel/sys/tasks.cpp index 7d471c33..371802b9 100644 --- a/kernel/sys/tasks.cpp +++ b/kernel/sys/tasks.cpp @@ -327,7 +327,7 @@ px_task_t *px_tasks_new(void (*entry)(void), px_task_t *storage, px_task_state s new_task->state = state; new_task->time_used = 0; new_task->name = name; - new_task->alloc = storage == NULL ? ALLOC_STATIC : ALLOC_DYNAMIC; + new_task->alloc = storage == NULL ? ALLOC_DYNAMIC : ALLOC_STATIC; if (state == TASK_READY) { _px_tasks_enqueue_ready(new_task); } From d112fe80ec3c29dccc5ff71343eb62581c3e97ba Mon Sep 17 00:00:00 2001 From: Micah Switzer Date: Wed, 30 Dec 2020 09:20:38 -0500 Subject: [PATCH 139/139] Add prime computing demo Per #184 --- kernel/apps/primes.cpp | 43 ++++++++++++++++++++++ kernel/main.cpp | 8 ++++ sysroot/usr/include/kernel/apps/primes.hpp | 4 ++ 3 files changed, 55 insertions(+) create mode 100644 kernel/apps/primes.cpp create mode 100644 sysroot/usr/include/kernel/apps/primes.hpp diff --git a/kernel/apps/primes.cpp b/kernel/apps/primes.cpp new file mode 100644 index 00000000..8b212ccd --- /dev/null +++ b/kernel/apps/primes.cpp @@ -0,0 +1,43 @@ +#include + +#include +#include +#include +#include + +// this value can be tweaked based on memory constraints +#define PRIME_MAX_SQRT 4000 +#define PRIME_MAX (PRIME_MAX_SQRT * PRIME_MAX_SQRT) +#define PRIMES_SIZE BITMAP_SIZE(PRIME_MAX) +static bitmap_t primes[PRIMES_SIZE]; + +static size_t prime_current; + +void find_primes(void) +{ + for (size_t i = 0; i < PRIMES_SIZE; i++) + primes[i] = SIZE_T_MAX_VALUE; + + for (prime_current = 2; prime_current < PRIME_MAX_SQRT; prime_current++) { + if (!bitmap_get_bit(primes, prime_current)) continue; + for (size_t j = prime_current * prime_current; j < PRIME_MAX; j += prime_current) { + bitmap_clear_bit(primes, j); + } + px_tasks_nano_sleep(1000ULL * 1000 * 100); + } +} + +void show_primes(void) +{ + do { + px_tasks_nano_sleep(1000ULL * 1000 * 1000); + size_t pct = (prime_current * 100) / PRIME_MAX_SQRT; + px_kprintf("\e[s\e[23;0fComputing primes: %%%u\e[u", pct); + } while (prime_current < PRIME_MAX_SQRT); + + size_t count = 0; + for (size_t i = 2; i < PRIME_MAX; i++) { + count += bitmap_get_bit(primes, i); + } + px_kprintf("\e[s\e[23;0fFound %u primes between 2 and %u.\e[u", count, PRIME_MAX); +} diff --git a/kernel/main.cpp b/kernel/main.cpp index f28342c4..081a6fd7 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -11,6 +11,7 @@ // System library functions #include #include +#include #include #include // Memory management & paging @@ -24,6 +25,8 @@ #include #include #include +// Apps +#include // Used as a magic number for stack smashing protection #if UINT32_MAX == UINTPTR_MAX @@ -93,6 +96,11 @@ extern "C" void px_kernel_main(const multiboot_info_t* mb_struct, uint32_t mb_ma // Done px_kprintf(DBG_OKAY "Done.\n"); + px_tasks_init(); + px_task_t compute, status; + px_tasks_new(find_primes, &compute, TASK_READY, "prime_compute"); + px_tasks_new(show_primes, &status, TASK_READY, "prime_display"); + // Now that we're done make a joyful noise px_kernel_boot_tone(); diff --git a/sysroot/usr/include/kernel/apps/primes.hpp b/sysroot/usr/include/kernel/apps/primes.hpp new file mode 100644 index 00000000..ebd68e96 --- /dev/null +++ b/sysroot/usr/include/kernel/apps/primes.hpp @@ -0,0 +1,4 @@ +#pragma once + +void find_primes(void); +void show_primes(void);