From b62706c9f2ceed65394457ae9b131996a2b29463 Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Fri, 24 Sep 2021 14:20:20 -0500 Subject: palloc/pfree found smp safe --- src/kernel/kernel.c | 6 ++-- src/kernel/page.c | 37 +++++++++++++++------ src/kernel/panic.c | 5 ++- src/kernel/printf.c | 2 +- src/kernel/smp.c | 1 + src/kernel/smp_racetest.c | 84 ++++++++++++++++++++++++++++++++++++++++++----- 6 files changed, 113 insertions(+), 22 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 0aa394e..bc5bae8 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -23,7 +23,7 @@ void kmain() { printf("Kernal started on core %i\n", get_coreid()); - sync_malloc(); + racetest(); PANIC(KERNEL_PANIC_KERNEL_RETURNED); } @@ -49,7 +49,6 @@ void kernel_init() { init_klog(); init_pmap(pmap_size); printf("\nKernal started on core 1!\n"); - //test_malloc(100); find_root_sdp(); @@ -66,6 +65,9 @@ void kernel_init() { //the rest of this needs to get done before the cores start executing init_pmap_smp(); + + + smp_unlocked = true; fix_stack(); diff --git a/src/kernel/page.c b/src/kernel/page.c index 0b286a4..c79b1fa 100644 --- a/src/kernel/page.c +++ b/src/kernel/page.c @@ -100,7 +100,6 @@ void fix_stack() { :"r"(PA_OFFSET)); while(frame->next != 0) { - printf("%p\n", frame->function_base); frame->next = PHYS_TO_VIRT((void *)frame->next); frame = frame->next; } @@ -171,14 +170,13 @@ void debug_pmap() { } } -//TODO I know you don't want to, but you need to thoroughly check this. void pfree(void *addr, size_t size) { int blevel = 0; uint64_t *onbyte; uint64_t page_bitloc; int bbitlen; int lshift; - pmap_t *pmap = first_pmap; + pmap_t *pmap; /* note: there's no security check to see if the page is actually allocated, * or if we are freeing the table itself. @@ -192,10 +190,13 @@ void pfree(void *addr, size_t size) { return; } size /= 0x1000; - for(; pmap != 0; pmap = pmap->next) { + for(pmap = first_pmap; pmap; pmap = pmap->next) { page_bitloc = (addr - (void *)pmap) / 0x1000; onbyte = pmap->buddy[0] + (page_bitloc / 64); - if((addr >= (void *)pmap) && onbyte < pmap->buddy[1]) break; + if((addr >= (void *)pmap) && onbyte < pmap->buddy[1]) { + lock(&pmap->mutex); + break; + } } while(blevel < MAX_BUDDY_ORDER) { @@ -241,6 +242,7 @@ void pfree(void *addr, size_t size) { blevel++; } } + unlock(&pmap->mutex); } @@ -276,13 +278,10 @@ void *palloc(size_t size) { self_alloc = false; min_blevel = 63 - __builtin_clzl(size); if(size & (size - 1)) min_blevel++; - if(min_blevel > MAX_BUDDY_ORDER - 1) return 0; + if(min_blevel > MAX_BUDDY_ORDER - 1) PANIC(KERNEL_PANIC_PALLOC_TOO_LARGE); } for(blevel = min_blevel; blevel < MAX_BUDDY_ORDER; blevel++) { - //for(pmap = first_pmap; pmap != 0; pmap = pmap->next) { - //while(!unlocked_pmaps_searched || - // is_empty(waiting_pmaps[core_id], sizeof(&pmap) * pmap_count)) { pmap = first_pmap; while(pmap) { @@ -329,12 +328,13 @@ void *palloc(size_t size) { return ret; } } -get_next_pmap: pmap->mutex = 0; +get_next_pmap: if(unlocked_pmaps_searched) { pmap = 0; for(searchingp_i = waitingp_i + 1; searchingp_i < pmap_count; searchingp_i++) { if(waiting_pmaps[waitlist_i(searchingp_i)]) { + waitingp_i = searchingp_i; pmap = waiting_pmaps[waitlist_i(searchingp_i)]; break; } @@ -342,6 +342,7 @@ get_next_pmap: if(!pmap) { for(searchingp_i = 0; searchingp_i <= waitingp_i; searchingp_i++) { if(waiting_pmaps[waitlist_i(searchingp_i)]) { + waitingp_i = searchingp_i; pmap = waiting_pmaps[waitlist_i(searchingp_i)]; break; } @@ -350,6 +351,7 @@ get_next_pmap: } else { if(!pmap->next) { + waitingp_i = 0; pmap = waiting_pmaps ? waiting_pmaps[waitlist_i(0)] : 0; unlocked_pmaps_searched = true; } @@ -515,3 +517,18 @@ void *init_pmap(size_t pagetable_size) { } return pmap; } + +void lock_all_maps() { + pmap_t *pmap; + for(pmap = first_pmap; pmap; pmap = pmap->next) pmap->mutex = 1; + pmap = first_pmap; + pmap_count++; + for(pmap = first_pmap;;pmap = pmap->next) { + if(!pmap->next) { + pmap->next = malloc(sizeof(pmap_t)); + pmap->next->mutex = 1; + break; + } + } + first_pmap->mutex = 0; +} diff --git a/src/kernel/panic.c b/src/kernel/panic.c index 06b37da..17a563d 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -6,7 +6,7 @@ #include #include -static uint8_t panic_lock = 0; +static uint16_t panic_lock = 0; void panic(int reason, void *eframe_p, struct registers *regs) { // will fill with debugging info latter lock(&panic_lock); @@ -56,6 +56,9 @@ void panic(int reason, void *eframe_p, struct registers *regs) { // will fill wi case KERNEL_PANIC_SMP_FAILED: printf("\nNot all cores booted successfully (see text before panic).\n"); break; + case KERNEL_PANIC_PALLOC_TOO_LARGE: + printf("\npalloc was called with a size greater then supported.\n"); + break; default: printf("\nUnknown panic code %i\n.", reason); break; diff --git a/src/kernel/printf.c b/src/kernel/printf.c index 62261ec..8e33981 100644 --- a/src/kernel/printf.c +++ b/src/kernel/printf.c @@ -873,7 +873,7 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const /////////////////////////////////////////////////////////////////////////////// -static uint8_t printf_lock = 0; +static uint16_t printf_lock = 0; int printf_(const char* format, ...) { //BRETT modification diff --git a/src/kernel/smp.c b/src/kernel/smp.c index a55fe49..662f9ed 100644 --- a/src/kernel/smp.c +++ b/src/kernel/smp.c @@ -101,6 +101,7 @@ void smp_prepare() { if(cores.apic_id[core_i] == cores.bsp) continue; stackarray[stack_i].apic_id = cores.apic_id[core_i]; stackarray[stack_i].stack = palloc(0x1000); + printf("core %i's stack: %lx\n", core_i, stackarray[stack_i].stack); stackarray[stack_i].secondary_bsp = (stack_i)? false : true; stack_i++; diff --git a/src/kernel/smp_racetest.c b/src/kernel/smp_racetest.c index f86e030..84321de 100644 --- a/src/kernel/smp_racetest.c +++ b/src/kernel/smp_racetest.c @@ -1,3 +1,6 @@ +//Disregard bad code here. +//I'm going to delete this whole file once I am confident smp is safe. + #define CHUNK_SIZE_FROM_INDEX(i) ((1 << ((i) + 5))) #include @@ -9,7 +12,7 @@ //will delete later -static uint8_t lockeroni = 0; +static uint16_t lockeroni = 0; void test_malloc(unsigned int cnt) { void *testchunks[cnt]; @@ -39,14 +42,79 @@ void test_malloc(unsigned int cnt) { printf("____________________________________\n"); unlock(&lockeroni); } -uint8_t cores_waiting = 4; -void sync_malloc() { - void *mtest; + +#define DEBUG_CORE_CNT 2 + +uint8_t cores_waiting = DEBUG_CORE_CNT; +uint8_t cores_waiting_2 = DEBUG_CORE_CNT; +uint8_t cores_waiting_3 = DEBUG_CORE_CNT; +uint8_t cores_waiting_4 = DEBUG_CORE_CNT; +uint8_t cores_waiting_5 = DEBUG_CORE_CNT; +void *smp_outputs[DEBUG_CORE_CNT]; + +void racetest() { + uint8_t core_id = get_coreid(); + uint8_t c_check; + unsigned int core_i; + asm("lock decb [%0]\n" - "spinlock:\n" + "spinlock_%=:\n" "cmpb [%0], 0\n" - "jnz spinlock\n" + "jnz spinlock_%=\n" ::"m"(cores_waiting)); - mtest = palloc(0x1000); - printf("Make sure none of these match -> %lx\n", mtest); + + smp_outputs[core_id] = palloc(0x1000); + printf("Make sure none of these match (palloc) -> %lx\n", smp_outputs[core_id]); + free(smp_outputs[core_id]); + + asm("lock decb [%0]\n" + "spinlock_%=:\n" + "cmpb [%0], 0\n" + "jnz spinlock_%=\n" + ::"m"(cores_waiting_2)); + + if(core_id == 0) { + for(core_i = 0; core_i < DEBUG_CORE_CNT; core_i++) { + for(c_check = core_i + 1; c_check < DEBUG_CORE_CNT; c_check++) { + if(smp_outputs[core_i] == smp_outputs[c_check]) { + printf("TEST FAILED\n"); + for(;;); + } + } + } + printf("TEST PASSED\n"); + printf("malloc beforehand: \n"); + debug_heap(); + } + + + asm("lock decb [%0]\n" + "spinlock_%=:\n" + "cmpb [%0], 0\n" + "jnz spinlock_%=\n" + ::"m"(cores_waiting_3)); + + + smp_outputs[core_id] = malloc(1); + printf("Make sure none of these match (malloc) -> %lx\n", smp_outputs[core_id]); + + asm("lock decb [%0]\n" + "spinlock_%=:\n" + "cmpb [%0], 0\n" + "jnz spinlock_%=\n" + ::"m"(cores_waiting_4)); + + if(core_id == 0) { + for(core_i = 0; core_i < DEBUG_CORE_CNT; core_i++) { + for(c_check = core_i + 1; c_check < DEBUG_CORE_CNT; c_check++) { + if(smp_outputs[core_i] == smp_outputs[c_check]) { + printf("TEST FAILED\n"); + for(;;); + } + } + } + printf("TEST PASSED\n"); + printf("malloc afterhand: \n"); + debug_heap(); + } } -- cgit v1.2.3