From cf7cd8be60c254b44b444c97dcb238d7cf3afd4c Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Tue, 21 Sep 2021 10:50:33 -0500 Subject: [PATCH] palloc smp safe (testing required, NOT pfree) --- src/debug/gdbinit.gdb | 3 + src/include/libc.h | 6 +- src/include/paging.h | 1 + src/include/random.h | 1 + src/include/smp.h | 23 +- src/include/{testmalloc.h => smp_racetest.h} | 0 src/include/smp_sync.h | 23 - src/indigo_os | Bin 43424 -> 45152 bytes src/kernel/heap.c | 6 +- src/kernel/kernel.c | 23 +- src/kernel/libc.c | 8 + src/kernel/page.c | 97 +++- src/kernel/random.c | 7 +- src/kernel/smp.c | 30 +- src/kernel/{testmalloc.c => smp_racetest.c} | 21 +- src/kernel/smp_trampoline.asm | 1 + src/makefile | 4 +- src/page_backup.c | 465 +++++++++++++++++++ 18 files changed, 663 insertions(+), 56 deletions(-) rename src/include/{testmalloc.h => smp_racetest.h} (100%) delete mode 100644 src/include/smp_sync.h rename src/kernel/{testmalloc.c => smp_racetest.c} (65%) create mode 100644 src/page_backup.c diff --git a/src/debug/gdbinit.gdb b/src/debug/gdbinit.gdb index a658ba4..516deba 100644 --- a/src/debug/gdbinit.gdb +++ b/src/debug/gdbinit.gdb @@ -1,6 +1,9 @@ target remote localhost:1234 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/libc.h b/src/include/libc.h index d0789cf..030f05f 100644 --- a/src/include/libc.h +++ b/src/include/libc.h @@ -2,10 +2,12 @@ #define _STRING_H_ #include #include +#include void *strcpy(char *dest, char *src); -void *memcpy(void *dest, void *src, size_t n); //TODO -void *bzero(const void *dest, size_t size); +void *memcpy(void *dest, void *src, size_t n); +void *bzero(void *dest, size_t size); +bool *is_empty(void *dest, size_t size); void *memset(void *s, char c, size_t n); size_t strlen(const char *s); int strcmp(const char *str1, const char *str2); diff --git a/src/include/paging.h b/src/include/paging.h index 5d33ca5..b1f8e9a 100644 --- a/src/include/paging.h +++ b/src/include/paging.h @@ -10,6 +10,7 @@ void unmap_lowmem(); size_t map_complete_physical(); void debug_pzone(); +void init_pmap_smp(); struct phys_map *init_pmap(size_t pagetable_size); diff --git a/src/include/random.h b/src/include/random.h index 6f35278..95b7147 100644 --- a/src/include/random.h +++ b/src/include/random.h @@ -1,5 +1,6 @@ #ifndef random_header #define random_header void randinit(); +void sync_malloc(); unsigned int randint(); #endif diff --git a/src/include/smp.h b/src/include/smp.h index f4e3aa8..e331036 100644 --- a/src/include/smp.h +++ b/src/include/smp.h @@ -1,7 +1,10 @@ #ifndef SMP_INCLUDED #define SMP_INCLUDED #include -void smp_boot(); +#include +#include +#include +void smp_prepare(); extern uint8_t corecount; static inline void lock(uint8_t *lock) { @@ -18,9 +21,25 @@ static inline void unlock(uint8_t *lock) { asm("lock andb [%0], 0"::"r"(lock)); } -static inline void waitup(uint8_t *loto) { +static inline bool get_set_mutex(uint16_t *mutex) { + bool ret; + asm("lock bts %1, 0\n" + "jc .mutex_taken\n" + "mov %0, 0\n" + "jmp .done\n" + ".mutex_taken:\n" + "mov %0, 1\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/testmalloc.h b/src/include/smp_racetest.h similarity index 100% rename from src/include/testmalloc.h rename to src/include/smp_racetest.h diff --git a/src/include/smp_sync.h b/src/include/smp_sync.h deleted file mode 100644 index 93aac35..0000000 --- a/src/include/smp_sync.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SMP_SYNC_INCLUDED -#define SMP_SYNC_INCLUDED - -static inline void lock(uint8_t *lock) { - asm("mov al, 1\n" - "spinlock:\n" - "lock xchgb [%0], al\n" - "test al, al\n" - "pause\n" - "jnz spinlock\n" - ::"r"(lock):"al"); -} - -static inline void unlock(uint8_t *lock) { - asm("lock andb [%0], 0"::"r"(lock)); -} - -static inline void waitup(uint8_t *loto) { -} - -#define CREATE_LOTO(name) - -#endif diff --git a/src/indigo_os b/src/indigo_os index 9a92fc500837cff34b20e449e6f35cc5395ab127..821f97a363d1b4fc83fd02da37db436c876761f6 100755 GIT binary patch delta 9955 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 diff --git a/src/kernel/heap.c b/src/kernel/heap.c index db6392f..e2dcbc7 100644 --- a/src/kernel/heap.c +++ b/src/kernel/heap.c @@ -26,10 +26,11 @@ typedef struct __attribute__((packed)) heap_chunk { - unsigned int free:1; unsigned int size:4; //will use with flags later if needed unsigned int lsize:4; - unsigned long reserved:55; + unsigned int free:1; + unsigned int mutex:1; + unsigned long reserved:54; struct heap_chunk *fd; struct heap_chunk *bk; } chunk; @@ -203,6 +204,7 @@ void *malloc(size_t size) { return (void *)on_chunk + sizeof(chunk); } + void *realloc(void *old_chunk, size_t size) { void *new_chunk = malloc(size); memcpy(new_chunk, old_chunk, CHUNK_SIZE_FROM_INDEX(((chunk *)(old_chunk-24))->size)); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index ab60f18..0aa394e 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -18,15 +18,24 @@ #include //testing headers -//#include +#include void kmain() { + printf("Kernal started on core %i\n", get_coreid()); + sync_malloc(); PANIC(KERNEL_PANIC_KERNEL_RETURNED); } +static bool smp_unlocked = false; void smp_kinit() { - printf("Kernal started on core <<<<< \n"); + + asm(".wait_for_release:\n" + "mov al, [%0]\n" + "test al, al\n" + "jz .wait_for_release\n" + ::"m"(smp_unlocked)); + smp_load_idt(); kmain(); } @@ -39,7 +48,8 @@ void kernel_init() { pmap_size = map_complete_physical(); init_klog(); init_pmap(pmap_size); - printf("\nKernal started on CPU 1!\n"); + printf("\nKernal started on core 1!\n"); + //test_malloc(100); find_root_sdp(); @@ -52,7 +62,12 @@ void kernel_init() { clear_screen(); debug_pzone(); - smp_boot(); + smp_prepare(); + + //the rest of this needs to get done before the cores start executing + init_pmap_smp(); + smp_unlocked = true; + fix_stack(); unmap_lowmem(); kmain(); diff --git a/src/kernel/libc.c b/src/kernel/libc.c index 4278281..f46c59f 100644 --- a/src/kernel/libc.c +++ b/src/kernel/libc.c @@ -1,5 +1,6 @@ #include #include +#include // TODO clean up variable names int strncmp(const char *s1, const char *s2, unsigned int n) { int i; @@ -18,6 +19,13 @@ size_t strlen(const char *s) { return(len); } +bool is_empty(const char *s, size_t size) { + for(size_t i = 0; i < size; i++) { + if(s[i]) return false; + } + return true; +} + int strcmp(const char *s1, const char *s2) { int i; for(i = 0; ((s1[i] != '\0') && (s2[i] != '\0')); i++) { diff --git a/src/kernel/page.c b/src/kernel/page.c index dea3941..0b286a4 100644 --- a/src/kernel/page.c +++ b/src/kernel/page.c @@ -7,11 +7,15 @@ #include #include #include +#include + +#include //just using char because c is a lil bitch and won't let us use void extern char _kernel_shared_zone_begin; - +//expects core_id +#define waitlist_i(y) (((core_id) * sizeof(uintptr_t)) + (y)) // PAGE MAPPING #define PAGEMAP_LOCATION 0x10000 @@ -22,12 +26,21 @@ extern char _kernel_shared_zone_begin; typedef struct phys_map { struct phys_map *next; unsigned int max_buddy; + + //has to be a 16 bit variable + uint16_t mutex; //we might improve the speed of this later + uint64_t bsize[MAX_BUDDY_ORDER]; uint64_t *buddy[MAX_BUDDY_ORDER]; } pmap_t; static pmap_t *first_pmap; +//I'd like to find out a way to get rid of this... we only use it once +static unsigned int pmap_count = 0; + +static pmap_t **waiting_pmaps; + #define MEM_AVAILABLE 1 #define MEM_RESERVED 2 #define MEM_APCI_RECLAIMABLE 3 @@ -161,10 +174,10 @@ 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; //the byte out buddy resides on in the current level - uint64_t page_bitloc; // how many bits we are away from buddy[0]. Helps calculate bitshifts - int bbitlen; //length of free'd area in current level - int lshift; //lshift is how many bits we shift over, rightbit is what it sounds like dumbass + uint64_t *onbyte; + uint64_t page_bitloc; + int bbitlen; + int lshift; pmap_t *pmap = first_pmap; /* note: there's no security check to see if the page is actually allocated, @@ -176,7 +189,7 @@ void pfree(void *addr, size_t size) { if(((uintptr_t)addr & 4095) || (size & 4095)) { PANIC(KERNEL_PANIC_INVALID_PFREE); - return; //TODO [minor] some more specificity, not a huge deal + return; } size /= 0x1000; for(; pmap != 0; pmap = pmap->next) { @@ -221,7 +234,7 @@ void pfree(void *addr, size_t size) { if(bbitlen <= 1) { *onbyte |= ((uint64_t)1 << lshift); break; - } else if(bbitlen & 1) { //check me + } else if(bbitlen & 1) { size -= (1 << blevel); *onbyte |= ((uint64_t)1 << (bbitlen + lshift)); } @@ -232,12 +245,16 @@ void pfree(void *addr, size_t size) { void *palloc(size_t size) { + uint8_t core_id = get_coreid(); bool self_alloc; int min_blevel, blevel; - uint64_t bbit, unshifted_entry, threshold, bloc; //TODO move when you've confirmed casting stuff + uint64_t bbit, unshifted_entry, threshold, bloc; uint64_t buddy_i, *ret, *bentry; int itercount; + bool unlocked_pmaps_searched = false; pmap_t *pmap = first_pmap; + unsigned int waitingp_i = 0; + unsigned int searchingp_i; if(size == 0) return 0; @@ -263,7 +280,19 @@ void *palloc(size_t size) { } for(blevel = min_blevel; blevel < MAX_BUDDY_ORDER; blevel++) { - for(pmap = first_pmap; pmap != 0; pmap = pmap->next) { + //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) { + + if(get_set_mutex(&pmap->mutex)) { + if(!unlocked_pmaps_searched) waiting_pmaps[waitlist_i(waitingp_i++)] = pmap; + goto get_next_pmap; + } + + + if(unlocked_pmaps_searched) waiting_pmaps[waitlist_i(waitingp_i)] = 0; for(buddy_i = 0; buddy_i < pmap->bsize[blevel]; buddy_i++) { if(pmap->buddy[blevel][buddy_i] > (uint64_t)0) { @@ -295,11 +324,42 @@ void *palloc(size_t size) { } *bentry |= (unshifted_entry << bloc); } - if(!self_alloc) bzero(ret, size * 0x1000); + pmap->mutex = 0; + if(!self_alloc) bzero(ret, size * 0x1000); //TODO do we really need to bezero here? return ret; } } +get_next_pmap: + pmap->mutex = 0; + 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)]) { + pmap = waiting_pmaps[waitlist_i(searchingp_i)]; + break; + } + } + if(!pmap) { + for(searchingp_i = 0; searchingp_i <= waitingp_i; searchingp_i++) { + if(waiting_pmaps[waitlist_i(searchingp_i)]) { + pmap = waiting_pmaps[waitlist_i(searchingp_i)]; + break; + } + } + } + } + else { + if(!pmap->next) { + pmap = waiting_pmaps ? waiting_pmaps[waitlist_i(0)] : 0; + unlocked_pmaps_searched = true; + } + else { + pmap = pmap->next; + } + } } + unlocked_pmaps_searched = false; + waitingp_i = 0; } return 0; } @@ -374,12 +434,19 @@ size_t map_complete_physical() { } } -pmap_t *init_pmap(size_t pagetable_size) { +void init_pmap_smp() { + size_t pmap_arrsize = corecount * pmap_count * sizeof(waiting_pmaps); + waiting_pmaps = malloc(pmap_arrsize); + bzero(waiting_pmaps, pmap_arrsize); +} + +void *init_pmap(size_t pagetable_size) { pmap_t *pmap, *last_pmap; struct memory_table *zones = (void *)ZONE_MAP; int budorder, zone_i; uint64_t pmap_size, pmap_bbitsize, zone_size; bool first_pmap_i = true; + @@ -387,6 +454,7 @@ pmap_t *init_pmap(size_t pagetable_size) { if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1) && zones[zone_i].length >= (0x2000)) { printf("found allocatable map at %p\n", zones[zone_i].base); + pmap_count++; last_pmap = pmap; if(zones[zone_i].base == (void *)0x100000) { zone_size = zones[zone_i].length - (((uint64_t)&_kernel_shared_zone_begin - 0x100000) + pagetable_size); @@ -396,7 +464,6 @@ pmap_t *init_pmap(size_t pagetable_size) { zone_size = zones[zone_i].length; pmap = PHYS_TO_VIRT(zones[zone_i].base); } - if(first_pmap_i) { pmap->next = NULL; first_pmap_i = false; @@ -405,6 +472,8 @@ pmap_t *init_pmap(size_t pagetable_size) { pmap->next = last_pmap; } + pmap->mutex = 0; + for(budorder = 0; budorder < MAX_BUDDY_ORDER; budorder++) { pmap_bbitsize = zone_size / (0x1000 << budorder); pmap->bsize[budorder] = DIV_ROUND_UP(pmap_bbitsize , 64); @@ -440,8 +509,8 @@ pmap_t *init_pmap(size_t pagetable_size) { } pmap_size = (uint64_t)(pmap->buddy[pmap->max_buddy] + pmap->bsize[pmap->max_buddy]) - (uint64_t)pmap; - first_pmap = pmap; //we spoof palloc into allocating from the specific required pmap. - palloc(pmap_size); //TODO (MAJOR BUG) something isn't right, I don't think + first_pmap = pmap; + palloc(pmap_size); } } return pmap; diff --git a/src/kernel/random.c b/src/kernel/random.c index 404223a..c959f6c 100644 --- a/src/kernel/random.c +++ b/src/kernel/random.c @@ -7,10 +7,9 @@ static bool hw_random = false; static unsigned long int seed = -1; void randinit() { - unsigned int unused, eax, ecx; - eax = 0; + unsigned int unused, ecx; ecx = 0; - __get_cpuid(1, &eax, &unused, &ecx, &unused); + __get_cpuid(1, &unused, &unused, &ecx, &unused); hw_random = (ecx >> 30) & 1; printf("Kernel random source: %s.\n", (hw_random) ? "rdrand" : "pseudo"); } @@ -31,6 +30,6 @@ unsigned int randint() { seed = 1103515245 * seed + 12345; return(unsigned int)(seed / 65536) % 32768; } - return 0; + return random_long; } diff --git a/src/kernel/smp.c b/src/kernel/smp.c index ff08f93..a55fe49 100644 --- a/src/kernel/smp.c +++ b/src/kernel/smp.c @@ -53,11 +53,30 @@ struct cpu_info { static struct gdt_descriptor gdtr; +struct cores_info cores; -void smp_boot() { +struct apicid_to_coreid_deleteme { //WILL BE DELETED AFTER THREADING EXISTS TODO + uint8_t apic_id; + uint8_t core_id; +}; + +static struct apicid_to_coreid_deleteme *apicid_to_coreid; + + +uint8_t get_coreid() { //WILL BE DELETED AFTER THREADING EXISTS TODO + uint32_t ebx, unused_cpuid; + uint8_t apic_id; + __get_cpuid(1, &unused_cpuid, &ebx, &unused_cpuid, &unused_cpuid); + apic_id = ebx >> 24; + for(uint8_t core = 0; core < corecount; core++) { + if(apicid_to_coreid[core].apic_id == apic_id) return apicid_to_coreid[core].core_id; + } + return 0; +} + +void smp_prepare() { uint8_t cores_active = 1; uint8_t stack_i = 0, core_i; - struct cores_info cores; struct icr_reg icr; struct cpu_info *stackarray; get_coreinfo(&cores); @@ -72,11 +91,18 @@ void smp_boot() { corecount = cores.corecount; stackarray = malloc(sizeof(struct cpu_info) * (cores.corecount - 1)); + apicid_to_coreid = malloc(sizeof(struct apicid_to_coreid_deleteme) * (cores.corecount - 1)); for(core_i = 0; core_i < cores.corecount; core_i++) { + + //WILL BE DELETED AFTER THREADING EXISTS TODO + apicid_to_coreid[core_i].apic_id = cores.apic_id[core_i]; + apicid_to_coreid[core_i].core_id = core_i; + 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); stackarray[stack_i].secondary_bsp = (stack_i)? false : true; + stack_i++; } for(stack_i = 0; stack_i < (cores.corecount - 1); stack_i++) { diff --git a/src/kernel/testmalloc.c b/src/kernel/smp_racetest.c similarity index 65% rename from src/kernel/testmalloc.c rename to src/kernel/smp_racetest.c index 5733c7c..f86e030 100644 --- a/src/kernel/testmalloc.c +++ b/src/kernel/smp_racetest.c @@ -4,9 +4,13 @@ #include #include #include +#include +#include //will delete later +static uint8_t lockeroni = 0; + void test_malloc(unsigned int cnt) { void *testchunks[cnt]; unsigned int rindex[cnt], testchunk_size, i, x; @@ -15,7 +19,7 @@ void test_malloc(unsigned int cnt) { for(x = 0; x < cnt; x++) { testchunk_size = (CHUNK_SIZE_FROM_INDEX(randint() % 7) - 24); testchunks[x] = malloc(testchunk_size); - //printf("ALLOCATING CHUNK %p SIZE %i\n", (void *)testchunks[x] - 24, testchunk_size); + printf("ALLOCATING CHUNK %p SIZE %i\n", (void *)testchunks[x] - 24, testchunk_size); } for(x = 0; x < cnt;) { i = randint() % cnt; @@ -23,13 +27,26 @@ void test_malloc(unsigned int cnt) { rindex[i] = x; x++; } + for(x = 0; x < cnt; x++) { //printf("FREEING CHUNK %p\n", (void *)testchunks[rindex[x]]); free(testchunks[rindex[x]]); } + printf("\nmalloc tester:\n"); printf("THIS NEEDS TO BE EMPTY______________\n"); debug_heap(); printf("____________________________________\n"); - + unlock(&lockeroni); +} +uint8_t cores_waiting = 4; +void sync_malloc() { + void *mtest; + asm("lock decb [%0]\n" + "spinlock:\n" + "cmpb [%0], 0\n" + "jnz spinlock\n" + ::"m"(cores_waiting)); + mtest = palloc(0x1000); + printf("Make sure none of these match -> %lx\n", mtest); } diff --git a/src/kernel/smp_trampoline.asm b/src/kernel/smp_trampoline.asm index 20c971e..cc91c3a 100644 --- a/src/kernel/smp_trampoline.asm +++ b/src/kernel/smp_trampoline.asm @@ -185,6 +185,7 @@ pause jnz .wait_for_gdt lgdt [final_gdt_descriptor] + mov rax, smp_kinit jmp rax diff --git a/src/makefile b/src/makefile index cbf3ce1..bb92e5f 100644 --- a/src/makefile +++ b/src/makefile @@ -1,5 +1,4 @@ LD=../compiler/indigo_gcc/bin/x86_64-elf-ld -#CC=../compiler/indigo_gcc/bin/x86_64-elf-gcc CC=../compiler/indigo_gcc/bin/x86_64-pc-linux-gnu-gcc OBJCPY=../compiler/indigo_gcc/bin/x86_64-elf-objcopy INC=-I./include @@ -60,6 +59,9 @@ smp_trampoline.o: run: qemu-system-x86_64 $(QEMU_OPTS) $(QEMU_PRINTDEBUG) -nographic +run_quiet: + qemu-system-x86_64 $(QEMU_OPTS) $(QEMU_PRINTDEBUG) -nographic 2>/dev/null + gdb: indigo_os tmux new-session -s os_gdb "qemu-system-x86_64 -S -s $(QEMU_OPTS) -nographic"\;\ split-window -h "gdb -x debug/gdbinit.gdb; killall qemu-system-x86_64" diff --git a/src/page_backup.c b/src/page_backup.c new file mode 100644 index 0000000..cf6834a --- /dev/null +++ b/src/page_backup.c @@ -0,0 +1,465 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//just using char because c is a lil bitch and won't let us use void +extern char _kernel_shared_zone_begin; + + + +// PAGE MAPPING +#define PAGEMAP_LOCATION 0x10000 + +#define MAX_BUDDY_ORDER 8 +#define PALLOC_AUTO_BLEVEL MAX_BUDDY_ORDER + +typedef struct phys_map { + struct phys_map *next; + unsigned int max_buddy; + + bool mutex; //we might improve the speed of this later + + uint64_t bsize[MAX_BUDDY_ORDER]; + uint64_t *buddy[MAX_BUDDY_ORDER]; +} pmap_t; + +static pmap_t *first_pmap; + +#define MEM_AVAILABLE 1 +#define MEM_RESERVED 2 +#define MEM_APCI_RECLAIMABLE 3 +#define MEM_APCI_NVS 4 +#define MEM_BAD 5 + +// ZONES +#define ZONE_MAP_PLOC 0x7000 +#define ZONE_MAP PHYS_TO_VIRT(ZONE_MAP_PLOC) + + + +//reorganized (moved) from header +typedef struct __attribute__((packed)) { + unsigned int present : 1; // present, must be one when accessed. + unsigned int read_write : 1; // if set to one, read and write is set + unsigned int user : 1; // For seperating CPL 0-2 and 3+ + unsigned int writethrough_cache : 1; // honestly maybe I should look into caching + unsigned int cachable : 1; // hardware chaching. 0 is enabled, whats the worst that could happen? + unsigned int accessed : 1; // we'll never use any of these! + unsigned int zg0 : 1; // needs to be (and will be) zero'd + unsigned int size : 1; // if set to 1, this entry points to physical memory + unsigned int zg1 : 1; // needs to be (and will be) zero'd + unsigned int software_marks : 3; // available for our own use, I doubt we'll use it in such a simple thing + + uintptr_t base_ptr : 40; + unsigned int avail:11; + unsigned int no_exec:1; +} page_table; + + +struct memory_table { + void *base; + uint64_t length; + uint32_t type; + uint32_t ACPI; +} __attribute__((packed)); + +static bool NX_capable; +static bool huge_page_capable; + + +void get_mem_capabilities() { + uint32_t unused, edx; + __get_cpuid(0x80000001, &unused, &unused, &unused, &edx); + huge_page_capable = (edx >> 26) & 1; + NX_capable = (edx >> 20) & 1; +} + +void fix_stack() { + struct stack_frame *frame; + + asm("addq rsp, %0\n" + "addq rbp, %0\n" + "mov %0, rbp" + :"=r"(frame) + :"r"(PA_OFFSET)); + + while(frame->next != 0) { + printf("%p\n", frame->function_base); + frame->next = PHYS_TO_VIRT((void *)frame->next); + frame = frame->next; + } +} + + +void unmap_lowmem() { + //[future] + //eventually, you should use the function that unmaps pages when you write it + page_table *entry = (page_table *)PAGEMAP_LOCATION; + entry[0].present = 0; +} + +void debug_pzone() { + struct memory_table *memtable = (void *)ZONE_MAP; + printf(" __________________________________________________________________________\n"); + printf("| type\tstart\t\t\tend\t\t\tsize\t\t |\n"); + printf("|--------------------------------------------------------------------------|\n"); + for(unsigned int i = 0; memtable[i].length > 0; i++) { + printf("| %u %u\t0x%p\t0x%p\t0x%p |\n", memtable[i].type, memtable[i].ACPI, memtable[i].base, (memtable[i].base + memtable[i].length), memtable[i].length); + } + printf("----------------------------------------------------------------------------\n"); +} + +void ram_stresser() { + struct memory_table *memtable = (void *)ZONE_MAP - PA_OFFSET; + memtable[6].length = 0x10000; +} + +void debug_pmap() { + pmap_t *pmap = first_pmap; + int pmap_i = 0, order; + uint64_t blong_i, bbit_i, buddy_chunksize, omit_cnt; + printf("Maximum buddy order: %u (up to %#x sized chunks)\n", MAX_BUDDY_ORDER, ((0x1000 << MAX_BUDDY_ORDER) - 1)); + for(; pmap != 0; pmap = pmap->next) { + printf("Table %u:\n" + "\tPhysical/pmap start:\t%#p\n" + "\tTable Size:\t%u\n", pmap_i, pmap, + (uint64_t)(pmap->buddy[MAX_BUDDY_ORDER - 1] + pmap->bsize[MAX_BUDDY_ORDER - 1]) - (uint64_t)pmap); + + for(order = 0; order <= MAX_BUDDY_ORDER - 1; order++) { + buddy_chunksize = (0x1000 << order); //TODO just put it in the for loop + printf("\tbuddy[%u]:\n" + "\t\tAddress:\t%#p\n" + "\t\tSize:\t\t%u\n" + "\t\tBuddies:\t\t\n", order, pmap->buddy[order], pmap->bsize[order]); + + omit_cnt = 0; + + for(blong_i = 0; blong_i < pmap->bsize[order]; blong_i++) { + for(bbit_i = 0; bbit_i < 64; bbit_i++) { + if((pmap->buddy[order][blong_i]) & ((uint64_t)1 << bbit_i)) { + if((omit_cnt < 20) || (blong_i == pmap->bsize[order] - 1)) { + printf("address %#p\tbit %u: %p\t is free\n", + pmap->buddy[order] + blong_i, + bbit_i, + ((uint64_t)pmap - PA_OFFSET) + ((((blong_i * 64) + bbit_i) * buddy_chunksize))); + } + omit_cnt++; + if(omit_cnt == 20) { + printf("\t\t\t[more entries ommited]\n"); + } + } + } + } + } + pmap_i++; + } +} + +//TODO I know you don't want to, but you need to thoroughly check this. +void pfree(void *addr, size_t size) { + int blevel = 0; + uint64_t *onbyte; //the byte out buddy resides on in the current level + uint64_t page_bitloc; // how many bits we are away from buddy[0]. Helps calculate bitshifts + int bbitlen; //length of free'd area in current level + int lshift; //lshift is how many bits we shift over, rightbit is what it sounds like dumbass + pmap_t *pmap = first_pmap; + + /* note: there's no security check to see if the page is actually allocated, + * or if we are freeing the table itself. + * This should be okay, as only the kernel will be calling it. + * If it gets too messy we can always come back. + */ + + + if(((uintptr_t)addr & 4095) || (size & 4095)) { + PANIC(KERNEL_PANIC_INVALID_PFREE); + return; //TODO [minor] some more specificity, not a huge deal + } + size /= 0x1000; + for(; pmap != 0; pmap = pmap->next) { + page_bitloc = (addr - (void *)pmap) / 0x1000; + onbyte = pmap->buddy[0] + (page_bitloc / 64); + if((addr >= (void *)pmap) && onbyte < pmap->buddy[1]) break; + } + + while(blevel < MAX_BUDDY_ORDER) { + lshift = (page_bitloc / (1 << blevel)) & 63; + onbyte = pmap->buddy[blevel] + ((page_bitloc / 64) / (1 << blevel)); + bbitlen = size / (1 << blevel); + + + //TODO clean up this part ------------------------------------------------------------- (below) + if(bbitlen <= 1) { + if(lshift & 1) { + if((*onbyte >> (lshift - 1)) & 1) { + *onbyte &= ~(((uint64_t)1 << (lshift - 1)) | ((uint64_t)1 << lshift)); + size += (1 << blevel); + page_bitloc -= (1 << blevel); + bbitlen = size / (1 << blevel); + } + } + else if((*onbyte >> (lshift + 1)) & 1) { + *onbyte &= ~(((uint64_t)1 << (lshift + 1)) | ((uint64_t)1 << lshift)); + size += (1 << blevel); + bbitlen = size / (1 << blevel); + } + } + else if(((lshift + bbitlen) & 1) && ((*onbyte >> (lshift + bbitlen)) & 1)) { + *onbyte ^= ((uint64_t)1 << (lshift + bbitlen)); + size += (1 << blevel); + bbitlen = size / (1 << blevel); + } + //TODO clean up this part ------------------------------------------------------------- (above) + + if((!((size - 1) & size)) && (bbitlen != 1)) { + blevel = 63 - __builtin_clzl(size); + } + else { + if(bbitlen <= 1) { + *onbyte |= ((uint64_t)1 << lshift); + break; + } else if(bbitlen & 1) { //check me + size -= (1 << blevel); + *onbyte |= ((uint64_t)1 << (bbitlen + lshift)); + } + blevel++; + } + } +} + + +void *palloc(size_t size) { + bool self_alloc; + int min_blevel, blevel; + uint64_t bbit, unshifted_entry, threshold, bloc; //TODO move when you've confirmed casting stuff + uint64_t buddy_i, *ret, *bentry; + int itercount; + pmap_t *pmap = first_pmap; + + + if(size == 0) return 0; + if(size & 4095) { + size = DIV_ROUND_UP(size, 0x1000); + } + else { + size = size / 0x1000; + } + + //checking if pmap has been initilized; if not we've been called to self allocate + //the first buddy should never be allocated; that's where our pmap lives + if(pmap->buddy[pmap->max_buddy][0] & 1) { + self_alloc = true; + min_blevel = pmap->max_buddy; + } + else { + //log(size, 2) + self_alloc = false; + min_blevel = 63 - __builtin_clzl(size); + if(size & (size - 1)) min_blevel++; + if(min_blevel > MAX_BUDDY_ORDER - 1) return 0; + } + + for(blevel = min_blevel; blevel < MAX_BUDDY_ORDER; blevel++) { + for(pmap = first_pmap; pmap != 0; pmap = pmap->next) { + //pmap->mutex = true; + /** + if(!maps_transversed && get_set_mutex(&pmap->mutex)) { + //change get_coreid once we multithread + asm("mov al, 1\n" + "mov cl, %0\n" + "shl al, cl\n" + "lock or [%1], al\n" + ::"r"(get_coreid()), "m"(pmap->threads_searched) + :); + } + **/ + + for(buddy_i = 0; buddy_i < pmap->bsize[blevel]; buddy_i++) { + if(pmap->buddy[blevel][buddy_i] > (uint64_t)0) { //found buddy + bentry = &pmap->buddy[blevel][buddy_i]; + bbit = __builtin_ctzl(*bentry); + bloc = bbit; + + *bentry ^= (uint64_t)1 << bbit; + + ret = (((buddy_i * 64) + bbit) * (0x1000 << blevel)) + (void *)pmap; + + threshold = 0b11; + + itercount = 1; + for(blevel--; blevel >= 0; blevel--) { + bentry = pmap->buddy[blevel] + ((bentry - pmap->buddy[blevel + 1]) * 2); + itercount++; + if(bloc >= 32) bentry += 1; + bloc = (bloc * 2) & 63; // will be the amount we need to shift + bbit = ceil((float)size / (1 << blevel)); + + + unshifted_entry = ((uint64_t)1 << bbit) & threshold; + if(unshifted_entry) { + threshold = ((uint64_t)1 << (bbit * 2)) - 1; + } + else { + threshold = (threshold << 2) | threshold; + } + *bentry |= (unshifted_entry << bloc); + } + if(!self_alloc) bzero(ret, size * 0x1000); //TODO do we really need to bezero here? + return ret; + } + } + } + } + return 0; +} + + +//returns size of pages needed +size_t map_complete_physical() { + uint64_t total_mem; + unsigned int pdpe_cnt, pde_cnt, pde_max_i; + int zone_i, entry_i; + struct memory_table *zones = (void *)ZONE_MAP_PLOC; + + + page_table *pml4 = (page_table *)PAGEMAP_LOCATION; + page_table *pdpe = (page_table *)&_kernel_shared_zone_begin; + page_table *pde; + + for(zone_i = 0; zones[zone_i].length > 0; zone_i++); + total_mem = (uint64_t)zones[zone_i - 1].base + zones[zone_i - 1].length; + + pdpe_cnt = (total_mem + (0x40000000 - 1)) / 0x40000000; + + + entry_i = (PA_OFFSET >> 39) & 0x1ff; + pml4[entry_i].base_ptr = (uintptr_t)&_kernel_shared_zone_begin >> 12; + pml4[entry_i].read_write = 1; + pml4[entry_i].user = 0; + pml4[entry_i].size = 0; + pml4[entry_i].no_exec = 1; + pml4[entry_i].present = 1; + + if(huge_page_capable) { + for(int pdpe_i = 0; pdpe_i < pdpe_cnt; pdpe_i++) { + pdpe[pdpe_i].base_ptr = pdpe_i << 18; + pdpe[pdpe_i].read_write = 1; + pdpe[pdpe_i].user = 0; + pdpe[pdpe_i].size = 1; + pdpe[pdpe_i].no_exec = NX_capable; + pdpe[pdpe_i].present = 1; + } + return pdpe_cnt * 0x1000; + } + else { + pde_cnt = (total_mem + 0x100000) / 0x200000; + for(int pdpe_i = 0; pdpe_i < pdpe_cnt; pdpe_i++) { + pde = (page_table *)(&_kernel_shared_zone_begin + (pdpe_cnt * 0x1000) + (pdpe_i * 0x1000)); + + if((pdpe_i < pdpe_cnt - 1) || (!(pde_cnt & 511))) { + pde_max_i = 512; + } + else { + pde_max_i = pde_cnt & 511; + } + + pdpe[pdpe_i].base_ptr = (uintptr_t)pde >> 12; + pdpe[pdpe_i].read_write = 1; + pdpe[pdpe_i].user = 0; + pdpe[pdpe_i].size = 0; + pdpe[pdpe_i].no_exec = NX_capable; + pdpe[pdpe_i].present = 1; + + for(int pde_i = 0; pde_i < pde_max_i; pde_i++) { + pde[pde_i].base_ptr = ((pdpe_i << 9) + pde_i) << 9; + pde[pde_i].read_write = 1; + pde[pde_i].user = 0; + pde[pde_i].size = 1; + pde[pde_i].no_exec = NX_capable; + pde[pde_i].present = 1; + } + } + return (pdpe_cnt * 2) * 0x1000; + } +} + +pmap_t *init_pmap(size_t pagetable_size) { + pmap_t *pmap, *last_pmap; + struct memory_table *zones = (void *)ZONE_MAP; + int budorder, zone_i; + uint64_t pmap_size, pmap_bbitsize, zone_size; + bool first_pmap_i = true; + + + + for(zone_i = 0; zones[zone_i].length > 0; zone_i++) { + if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1) && + zones[zone_i].length >= (0x2000)) { + printf("found allocatable map at %p\n", zones[zone_i].base); + last_pmap = pmap; + if(zones[zone_i].base == (void *)0x100000) { + zone_size = zones[zone_i].length - (((uint64_t)&_kernel_shared_zone_begin - 0x100000) + pagetable_size); + pmap = PHYS_TO_VIRT((void *)&_kernel_shared_zone_begin + pagetable_size); + } + else { + zone_size = zones[zone_i].length; + pmap = PHYS_TO_VIRT(zones[zone_i].base); + } + if(first_pmap_i) { + pmap->next = NULL; + first_pmap_i = false; + } + else { + pmap->next = last_pmap; + } + + pmap->mutex = false; + + for(budorder = 0; budorder < MAX_BUDDY_ORDER; budorder++) { + pmap_bbitsize = zone_size / (0x1000 << budorder); + pmap->bsize[budorder] = DIV_ROUND_UP(pmap_bbitsize , 64); + if(budorder) { + pmap->buddy[budorder] = pmap->buddy[budorder - 1] + pmap->bsize[budorder - 1]; + } + else { + pmap->buddy[0] = (void *)pmap + sizeof(*pmap); + } + if(budorder < MAX_BUDDY_ORDER - 1) { + bzero(pmap->buddy[budorder], pmap->bsize[budorder] * 8); + if(pmap_bbitsize & 1) { + pmap->buddy[budorder][pmap->bsize[budorder] - 1] = + ((uint64_t)1 << ((pmap_bbitsize - 1) & 63)); + } + if(pmap_bbitsize == 1) { + pmap->max_buddy = budorder; + for(budorder++; budorder < MAX_BUDDY_ORDER; budorder++) { + pmap->buddy[budorder] = 0; + pmap->bsize[budorder] = 0; + } + break; + } + } + else { + pmap->max_buddy = MAX_BUDDY_ORDER - 1; + memset(pmap->buddy[budorder], UINT8_MAX, pmap->bsize[budorder] * 8); + if((pmap_bbitsize / 64) != (pmap->bsize[budorder])) { + pmap->buddy[budorder][pmap->bsize[budorder] - 1] = + (((uint64_t)1 << (pmap_bbitsize & 63)) - 1); + } + } + } + + pmap_size = (uint64_t)(pmap->buddy[pmap->max_buddy] + pmap->bsize[pmap->max_buddy]) - (uint64_t)pmap; + first_pmap = pmap; //we spoof palloc into allocating from the specific required pmap. + palloc(pmap_size); + } + } + return pmap; +}