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/debug/gdbinit.gdb | 1 - src/include/panic.h | 1 + src/include/smp.h | 30 ++++++++++++---- src/include/smp_racetest.h | 2 +- src/indigo_os | Bin 45152 -> 0 bytes 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 ++++++++++++++++++++++++++++++++++++++++----- 11 files changed, 138 insertions(+), 31 deletions(-) delete mode 100755 src/indigo_os (limited to 'src') diff --git a/src/debug/gdbinit.gdb b/src/debug/gdbinit.gdb index 516deba..b8aa7f5 100644 --- a/src/debug/gdbinit.gdb +++ b/src/debug/gdbinit.gdb @@ -3,7 +3,6 @@ symbol-file debug/debug_syms.o set scheduler-locking step -hb page.c:357 define cs2bs print (1 << (5 + $arg0)) diff --git a/src/include/panic.h b/src/include/panic.h index 43712a2..29e9f85 100644 --- a/src/include/panic.h +++ b/src/include/panic.h @@ -53,6 +53,7 @@ void panic(int reason, void *frame_p, struct registers *regs); #define KERNEL_PANIC_INVALID_IOAPIC_VEC 36 #define KERNEL_PANIC_HPET_REQUIRED 37 #define KERNEL_PANIC_SMP_FAILED 38 +#define KERNEL_PANIC_PALLOC_TOO_LARGE 39 #define DEV_EMAIL "brett_weiland@bpcspace.com" diff --git a/src/include/smp.h b/src/include/smp.h index e331036..ba12c76 100644 --- a/src/include/smp.h +++ b/src/include/smp.h @@ -7,6 +7,7 @@ void smp_prepare(); extern uint8_t corecount; +/** static inline void lock(uint8_t *lock) { asm("mov al, 1\n" "spinlock:\n" @@ -16,30 +17,45 @@ static inline void lock(uint8_t *lock) { "jnz spinlock\n" ::"r"(lock):"al"); } +**/ +static inline void lock(uint16_t *mutex) { + asm(".spinlock_%=:\n" + "lock bts %0, 0\n" + "jnc .done_%=\n" + "pause\n" + "jmp .spinlock_%=\n" + ".done_%=:\n" + ::"m"(*mutex)); +} + +static inline void unlock(uint16_t *mutex) { + asm("lock btr %0, 0\n" + ::"m"(*mutex)); +} + +/** static inline void unlock(uint8_t *lock) { asm("lock andb [%0], 0"::"r"(lock)); } +**/ static inline bool get_set_mutex(uint16_t *mutex) { bool ret; asm("lock bts %1, 0\n" - "jc .mutex_taken\n" + "jc .mutex_taken_%=\n" "mov %0, 0\n" - "jmp .done\n" - ".mutex_taken:\n" + "jmp .done_%=\n" + ".mutex_taken_%=:\n" "mov %0, 1\n" - ".done:\n" + ".done_%=:\n" :"=r"(ret) :"m"(*mutex)); return ret; } - - //THIS IS ONLY UNTIL WE GET MULTITHREADING SET UP uint8_t get_coreid(); -#define CREATE_LOTO(name) #endif diff --git a/src/include/smp_racetest.h b/src/include/smp_racetest.h index 25ab7f3..f30c3be 100644 --- a/src/include/smp_racetest.h +++ b/src/include/smp_racetest.h @@ -1,6 +1,6 @@ #ifndef testmalloc_header #define testmalloc_header -void test_malloc(unsigned int cnt); +void racetest(); #endif diff --git a/src/indigo_os b/src/indigo_os deleted file mode 100755 index 821f97a..0000000 Binary files a/src/indigo_os and /dev/null differ 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