From bd9f994648ffc1934ffc490b0c3e4f94849ca8eb Mon Sep 17 00:00:00 2001 From: Curle Date: Wed, 17 Mar 2021 01:23:36 +0000 Subject: [PATCH] Adjustments to the virtual memory manager, add Liballoc for kmalloc and kfree. --- chroma/inc/kernel/system/memory.h | 11 +- chroma/system/memory/liballoc.c | 876 ++++++++++++++++++++++++++++++ chroma/system/memory/paging.c | 16 +- chroma/system/memory/physmem.c | 4 +- 4 files changed, 897 insertions(+), 10 deletions(-) create mode 100644 chroma/system/memory/liballoc.c diff --git a/chroma/inc/kernel/system/memory.h b/chroma/inc/kernel/system/memory.h index 14ed382..830df48 100644 --- a/chroma/inc/kernel/system/memory.h +++ b/chroma/inc/kernel/system/memory.h @@ -142,6 +142,8 @@ #define TO_DIRECT(addr) ((size_t)(addr) + DIRECT_REGION) #define FROM_DIRECT(addr) ((size_t)(addr) - DIRECT_REGION) +#define PREFIX(func) k ## func + /********************************************* * T Y P E D E F I N I T I O N S **********************************************/ @@ -244,7 +246,7 @@ void PhysRefPage(directptr_t Page); void PhysFreePage(directptr_t Page); -void FreePhysMem(directptr_t Phys); +void PhysFreeMem(directptr_t Phys, size_t count); size_t SeekFrame(); @@ -280,4 +282,9 @@ void* AllocateKernelStack(); void FreeKernelStack(void* StackAddress); -void PageFaultHandler(INTERRUPT_FRAME Frame); \ No newline at end of file +void PageFaultHandler(INTERRUPT_FRAME Frame); + +extern void *PREFIX(malloc)(size_t); ///< The standard function. +extern void *PREFIX(realloc)(void *, size_t); ///< The standard function. +extern void *PREFIX(calloc)(size_t, size_t); ///< The standard function. +extern void PREFIX(free)(void *); ///< The standard function. \ No newline at end of file diff --git a/chroma/system/memory/liballoc.c b/chroma/system/memory/liballoc.c new file mode 100644 index 0000000..4ff4460 --- /dev/null +++ b/chroma/system/memory/liballoc.c @@ -0,0 +1,876 @@ +#include +#include + +/** Durand's Amazing Super Duper Memory functions. */ + +#define VERSION "1.1" +#define ALIGNMENT 16ul//4ul ///< This is the byte alignment that memory must be allocated on. IMPORTANT for GTK and other stuff. + +#define ALIGN_TYPE char ///unsigned char[16] /// unsigned short +#define ALIGN_INFO sizeof(ALIGN_TYPE)*16 ///< Alignment information is stored right before the pointer. This is the number of bytes of information stored there. + + +#define USE_CASE1 +#define USE_CASE2 +#define USE_CASE3 +#define USE_CASE4 +#define USE_CASE5 + +extern address_space_t KernelAddressSpace; + +/** 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. + */ +static int liballoc_lock() { + return TicketAttemptLock(&KernelAddressSpace.Lock) ? 0 : 1; +} + +/** 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. + * + */ +static void liballoc_unlock() { + TicketUnlock(&KernelAddressSpace.Lock); +} + +/** 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. + */ +static void* liballoc_alloc(size_t count) { + return (void*) PhysAllocateMem(count * PAGE_SIZE); +} + +/** 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. + */ +static int liballoc_free(void* ptr, size_t count) { + PhysFreeMem(ptr, count * PAGE_SIZE); + return 0; +} + + +/** This macro will conveniently align our pointer upwards */ +#define ALIGN( ptr ) \ + if ( ALIGNMENT > 1 ) \ + { \ + uintptr_t diff; \ + ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ + diff = (uintptr_t)ptr & (ALIGNMENT-1); \ + if ( diff != 0 ) \ + { \ + diff = ALIGNMENT - diff; \ + ptr = (void*)((uintptr_t)ptr + diff); \ + } \ + *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \ + diff + ALIGN_INFO; \ + } + + +#define UNALIGN( ptr ) \ + if ( ALIGNMENT > 1 ) \ + { \ + uintptr_t diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \ + if ( diff < (ALIGNMENT + ALIGN_INFO) ) \ + { \ + ptr = (void*)((uintptr_t)ptr - diff); \ + } \ + } + + + +#define LIBALLOC_MAGIC 0xc001c0de +#define LIBALLOC_DEAD 0xdeaddead + +#if defined DEBUG || defined INFO +#include +#include + +#define FLUSH() fflush( stdout ) + +#endif + +/** A structure found at the top of all system allocated + * memory blocks. It details the usage of the memory block. + */ +struct liballoc_major +{ + struct liballoc_major *prev; ///< Linked list information. + struct liballoc_major *next; ///< Linked list information. + unsigned int pages; ///< The number of pages in the block. + unsigned int size; ///< The number of pages in the block. + unsigned int usage; ///< The number of bytes used in the block. + struct liballoc_minor *first; ///< A pointer to the first allocated memory in the block. +}; + + +/** This is a structure found at the beginning of all + * sections in a major block which were allocated by a + * malloc, calloc, realloc call. + */ +struct liballoc_minor +{ + struct liballoc_minor *prev; ///< Linked list information. + struct liballoc_minor *next; ///< Linked list information. + struct liballoc_major *block; ///< The owning block. A pointer to the major structure. + unsigned int magic; ///< A magic number to idenfity correctness. + unsigned int size; ///< The size of the memory allocated. Could be 1 byte or more. + unsigned int req_size; ///< The size of memory requested. +}; + + +static struct liballoc_major *l_memRoot = NULL; ///< The root memory block acquired from the system. +static struct liballoc_major *l_bestBet = NULL; ///< The major with the most free memory. + +static unsigned int l_pageSize = 4096; ///< The size of an individual page. Set up in liballoc_init. +static unsigned int l_pageCount = 16; ///< The number of pages to request per chunk. Set up in liballoc_init. +static unsigned long long l_allocated = 0; ///< Running total of allocated memory. +static unsigned long long l_inuse = 0; ///< Running total of used memory. + + +static long long l_warningCount = 0; ///< Number of warnings encountered +static long long l_errorCount = 0; ///< Number of actual errors +static long long l_possibleOverruns = 0; ///< Number of possible overruns + + + + + +// *********** HELPER FUNCTIONS ******************************* + +static void *liballoc_memset(void* s, int c, size_t n) +{ + unsigned int i; + for ( i = 0; i < n ; i++) + ((char*)s)[i] = c; + + return s; +} +static void* liballoc_memcpy(void* s1, const void* s2, size_t n) +{ + char *cdest; + char *csrc; + unsigned int *ldest = (unsigned int*)s1; + unsigned int *lsrc = (unsigned int*)s2; + + while ( n >= sizeof(unsigned int) ) + { + *ldest++ = *lsrc++; + n -= sizeof(unsigned int); + } + + cdest = (char*)ldest; + csrc = (char*)lsrc; + + while ( n > 0 ) + { + *cdest++ = *csrc++; + n -= 1; + } + + return s1; +} + + +#if defined DEBUG || defined INFO +static void liballoc_dump() +{ +#ifdef DEBUG + struct liballoc_major *maj = l_memRoot; + struct liballoc_minor *min = NULL; +#endif + + printf( "liballoc: ------ Memory data ---------------\n"); + printf( "liballoc: System memory allocated: %i bytes\n", l_allocated ); + printf( "liballoc: Memory in used (malloc'ed): %i bytes\n", l_inuse ); + printf( "liballoc: Warning count: %i\n", l_warningCount ); + printf( "liballoc: Error count: %i\n", l_errorCount ); + printf( "liballoc: Possible overruns: %i\n", l_possibleOverruns ); + +#ifdef DEBUG + while ( maj != NULL ) + { + printf( "liballoc: %x: total = %i, used = %i\n", + maj, + maj->size, + maj->usage ); + + min = maj->first; + while ( min != NULL ) + { + printf( "liballoc: %x: %i bytes\n", + min, + min->size ); + min = min->next; + } + + maj = maj->next; + } +#endif + + FLUSH(); +} +#endif + + + +// *************************************************************** + +static struct liballoc_major *allocate_new_page( unsigned int size ) +{ + unsigned int st; + struct liballoc_major *maj; + + // This is how much space is required. + st = size + sizeof(struct liballoc_major); + st += sizeof(struct liballoc_minor); + + // Perfect amount of space? + if ( (st % l_pageSize) == 0 ) + st = st / (l_pageSize); + else + st = st / (l_pageSize) + 1; + // No, add the buffer. + + + // Make sure it's >= the minimum size. + if ( st < l_pageCount ) st = l_pageCount; + + maj = (struct liballoc_major*)liballoc_alloc( st ); + + if ( maj == NULL ) + { + l_warningCount += 1; + #if defined DEBUG || defined INFO + printf( "liballoc: WARNING: liballoc_alloc( %i ) return NULL\n", st ); + FLUSH(); + #endif + return NULL; // uh oh, we ran out of memory. + } + + maj->prev = NULL; + maj->next = NULL; + maj->pages = st; + maj->size = st * l_pageSize; + maj->usage = sizeof(struct liballoc_major); + maj->first = NULL; + + l_allocated += maj->size; + + #ifdef DEBUG + printf( "liballoc: Resource allocated %x of %i pages (%i bytes) for %i size.\n", maj, st, maj->size, size ); + + printf( "liballoc: Total memory usage = %i KB\n", (int)((l_allocated / (1024))) ); + FLUSH(); + #endif + + + return maj; +} + + + + + +void *PREFIX(malloc)(size_t req_size) +{ + int startedBet = 0; + unsigned long long bestSize = 0; + void *p = NULL; + uintptr_t diff; + struct liballoc_major *maj; + struct liballoc_minor *min; + struct liballoc_minor *new_min; + unsigned long size = req_size; + + // For alignment, we adjust size so there's enough space to align. + if ( ALIGNMENT > 1 ) + { + size += ALIGNMENT + ALIGN_INFO; + } + // So, ideally, we really want an alignment of 0 or 1 in order + // to save space. + + liballoc_lock(); + + if ( size == 0 ) + { + l_warningCount += 1; + #if defined DEBUG || defined INFO + printf( "liballoc: WARNING: alloc( 0 ) called from %x\n", + __builtin_return_address(0) ); + FLUSH(); + #endif + liballoc_unlock(); + return PREFIX(malloc)(1); + } + + + if ( l_memRoot == NULL ) + { + #if defined DEBUG || defined INFO + #ifdef DEBUG + printf( "liballoc: initialization of liballoc " VERSION "\n" ); + #endif + atexit( liballoc_dump ); + FLUSH(); + #endif + + // This is the first time we are being used. + l_memRoot = allocate_new_page( size ); + if ( l_memRoot == NULL ) + { + liballoc_unlock(); + #ifdef DEBUG + printf( "liballoc: initial l_memRoot initialization failed\n", p); + FLUSH(); + #endif + return NULL; + } + + #ifdef DEBUG + printf( "liballoc: set up first memory major %x\n", l_memRoot ); + FLUSH(); + #endif + } + + + #ifdef DEBUG + printf( "liballoc: %x PREFIX(malloc)( %i ): ", + __builtin_return_address(0), + size ); + FLUSH(); + #endif + + // Now we need to bounce through every major and find enough space.... + + maj = l_memRoot; + startedBet = 0; + + // Start at the best bet.... + if ( l_bestBet != NULL ) + { + bestSize = l_bestBet->size - l_bestBet->usage; + + if ( bestSize > (size + sizeof(struct liballoc_minor))) + { + maj = l_bestBet; + startedBet = 1; + } + } + + while ( maj != NULL ) + { + diff = maj->size - maj->usage; + // free memory in the block + + if ( bestSize < diff ) + { + // Hmm.. this one has more memory then our bestBet. Remember! + l_bestBet = maj; + bestSize = diff; + } + + +#ifdef USE_CASE1 + + // CASE 1: There is not enough space in this major block. + if ( diff < (size + sizeof( struct liballoc_minor )) ) + { + #ifdef DEBUG + printf( "CASE 1: Insufficient space in block %x\n", maj); + FLUSH(); + #endif + + // Another major block next to this one? + if ( maj->next != NULL ) + { + maj = maj->next; // Hop to that one. + continue; + } + + if ( startedBet == 1 ) // If we started at the best bet, + { // let's start all over again. + maj = l_memRoot; + startedBet = 0; + continue; + } + + // Create a new major block next to this one and... + maj->next = allocate_new_page( size ); // next one will be okay. + if ( maj->next == NULL ) break; // no more memory. + maj->next->prev = maj; + maj = maj->next; + + // .. fall through to CASE 2 .. + } + +#endif + +#ifdef USE_CASE2 + + // CASE 2: It's a brand new block. + if ( maj->first == NULL ) + { + maj->first = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major) ); + + + maj->first->magic = LIBALLOC_MAGIC; + maj->first->prev = NULL; + maj->first->next = NULL; + maj->first->block = maj; + maj->first->size = size; + maj->first->req_size = req_size; + maj->usage += size + sizeof( struct liballoc_minor ); + + + l_inuse += size; + + + p = (void*)((uintptr_t)(maj->first) + sizeof( struct liballoc_minor )); + + ALIGN( p ); + + #ifdef DEBUG + printf( "CASE 2: returning %x\n", p); + FLUSH(); + #endif + liballoc_unlock(); // release the lock + return p; + } + +#endif + +#ifdef USE_CASE3 + + // CASE 3: Block in use and enough space at the start of the block. + diff = (uintptr_t)(maj->first); + diff -= (uintptr_t)maj; + diff -= sizeof(struct liballoc_major); + + if ( diff >= (size + sizeof(struct liballoc_minor)) ) + { + // Yes, space in front. Squeeze in. + maj->first->prev = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major) ); + maj->first->prev->next = maj->first; + maj->first = maj->first->prev; + + maj->first->magic = LIBALLOC_MAGIC; + maj->first->prev = NULL; + maj->first->block = maj; + maj->first->size = size; + maj->first->req_size = req_size; + maj->usage += size + sizeof( struct liballoc_minor ); + + l_inuse += size; + + p = (void*)((uintptr_t)(maj->first) + sizeof( struct liballoc_minor )); + ALIGN( p ); + + #ifdef DEBUG + printf( "CASE 3: returning %x\n", p); + FLUSH(); + #endif + liballoc_unlock(); // release the lock + return p; + } + +#endif + + +#ifdef USE_CASE4 + + // CASE 4: There is enough space in this block. But is it contiguous? + min = maj->first; + + // Looping within the block now... + while ( min != NULL ) + { + // CASE 4.1: End of minors in a block. Space from last and end? + if ( min->next == NULL ) + { + // the rest of this block is free... is it big enough? + diff = (uintptr_t)(maj) + maj->size; + diff -= (uintptr_t)min; + diff -= sizeof( struct liballoc_minor ); + diff -= min->size; + // minus already existing usage.. + + if ( diff >= (size + sizeof( struct liballoc_minor )) ) + { + // yay.... + min->next = (struct liballoc_minor*)((uintptr_t)min + sizeof( struct liballoc_minor ) + min->size); + min->next->prev = min; + min = min->next; + min->next = NULL; + min->magic = LIBALLOC_MAGIC; + min->block = maj; + min->size = size; + min->req_size = req_size; + maj->usage += size + sizeof( struct liballoc_minor ); + + l_inuse += size; + + p = (void*)((uintptr_t)min + sizeof( struct liballoc_minor )); + ALIGN( p ); + + #ifdef DEBUG + printf( "CASE 4.1: returning %x\n", p); + FLUSH(); + #endif + liballoc_unlock(); // release the lock + return p; + } + } + + + + // CASE 4.2: Is there space between two minors? + if ( min->next != NULL ) + { + // is the difference between here and next big enough? + diff = (uintptr_t)(min->next); + diff -= (uintptr_t)min; + diff -= sizeof( struct liballoc_minor ); + diff -= min->size; + // minus our existing usage. + + if ( diff >= (size + sizeof( struct liballoc_minor )) ) + { + // yay...... + new_min = (struct liballoc_minor*)((uintptr_t)min + sizeof( struct liballoc_minor ) + min->size); + + new_min->magic = LIBALLOC_MAGIC; + new_min->next = min->next; + new_min->prev = min; + new_min->size = size; + new_min->req_size = req_size; + new_min->block = maj; + min->next->prev = new_min; + min->next = new_min; + maj->usage += size + sizeof( struct liballoc_minor ); + + l_inuse += size; + + p = (void*)((uintptr_t)new_min + sizeof( struct liballoc_minor )); + ALIGN( p ); + + + #ifdef DEBUG + printf( "CASE 4.2: returning %x\n", p); + FLUSH(); + #endif + + liballoc_unlock(); // release the lock + return p; + } + } // min->next != NULL + + min = min->next; + } // while min != NULL ... + + +#endif + +#ifdef USE_CASE5 + + // CASE 5: Block full! Ensure next block and loop. + if ( maj->next == NULL ) + { + #ifdef DEBUG + printf( "CASE 5: block full\n"); + FLUSH(); + #endif + + if ( startedBet == 1 ) + { + maj = l_memRoot; + startedBet = 0; + continue; + } + + // we've run out. we need more... + maj->next = allocate_new_page( size ); // next one guaranteed to be okay + if ( maj->next == NULL ) break; // uh oh, no more memory..... + maj->next->prev = maj; + + } + +#endif + + maj = maj->next; + } // while (maj != NULL) + + + + liballoc_unlock(); // release the lock + + #ifdef DEBUG + printf( "All cases exhausted. No memory available.\n"); + FLUSH(); + #endif + #if defined DEBUG || defined INFO + printf( "liballoc: WARNING: PREFIX(malloc)( %i ) returning NULL.\n", size); + liballoc_dump(); + FLUSH(); + #endif + return NULL; +} + + + + + + + + + +void PREFIX(free)(void *ptr) +{ + struct liballoc_minor *min; + struct liballoc_major *maj; + + if ( ptr == NULL ) + { + l_warningCount += 1; + #if defined DEBUG || defined INFO + printf( "liballoc: WARNING: PREFIX(free)( NULL ) called from %x\n", + __builtin_return_address(0) ); + FLUSH(); + #endif + return; + } + + UNALIGN( ptr ); + + liballoc_lock(); // lockit + + + min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof( struct liballoc_minor )); + + + if ( min->magic != LIBALLOC_MAGIC ) + { + l_errorCount += 1; + + // Check for overrun errors. For all bytes of LIBALLOC_MAGIC + if ( + ((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || + ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || + ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF)) + ) + { + l_possibleOverruns += 1; + #if defined DEBUG || defined INFO + printf( "liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n", + min->magic, + LIBALLOC_MAGIC ); + FLUSH(); + #endif + } + + + if ( min->magic == LIBALLOC_DEAD ) + { + #if defined DEBUG || defined INFO + printf( "liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n", + ptr, + __builtin_return_address(0) ); + FLUSH(); + #endif + } + else + { + #if defined DEBUG || defined INFO + printf( "liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n", + ptr, + __builtin_return_address(0) ); + FLUSH(); + #endif + } + + // being lied to... + liballoc_unlock(); // release the lock + return; + } + + #ifdef DEBUG + printf( "liballoc: %x PREFIX(free)( %x ): ", + __builtin_return_address( 0 ), + ptr ); + FLUSH(); + #endif + + + maj = min->block; + + l_inuse -= min->size; + + maj->usage -= (min->size + sizeof( struct liballoc_minor )); + min->magic = LIBALLOC_DEAD; // No mojo. + + if ( min->next != NULL ) min->next->prev = min->prev; + if ( min->prev != NULL ) min->prev->next = min->next; + + if ( min->prev == NULL ) maj->first = min->next; + // Might empty the block. This was the first + // minor. + + + // We need to clean up after the majors now.... + + if ( maj->first == NULL ) // Block completely unused. + { + if ( l_memRoot == maj ) l_memRoot = maj->next; + if ( l_bestBet == maj ) l_bestBet = NULL; + if ( maj->prev != NULL ) maj->prev->next = maj->next; + if ( maj->next != NULL ) maj->next->prev = maj->prev; + l_allocated -= maj->size; + + liballoc_free( maj, maj->pages ); + } + else + { + if ( l_bestBet != NULL ) + { + int bestSize = l_bestBet->size - l_bestBet->usage; + int majSize = maj->size - maj->usage; + + if ( majSize > bestSize ) l_bestBet = maj; + } + + } + + + #ifdef DEBUG + printf( "OK\n"); + FLUSH(); + #endif + + liballoc_unlock(); // release the lock +} + + + + + +void* PREFIX(calloc)(size_t nobj, size_t size) +{ + int real_size; + void *p; + + real_size = nobj * size; + + p = PREFIX(malloc)( real_size ); + + liballoc_memset( p, 0, real_size ); + + return p; +} + + + +void* PREFIX(realloc)(void *p, size_t size) +{ + void *ptr; + struct liballoc_minor *min; + unsigned int real_size; + + // Honour the case of size == 0 => free old and return NULL + if ( size == 0 ) + { + PREFIX(free)( p ); + return NULL; + } + + // In the case of a NULL pointer, return a simple malloc. + if ( p == NULL ) return PREFIX(malloc)( size ); + + // Unalign the pointer if required. + ptr = p; + UNALIGN(ptr); + + liballoc_lock(); // lockit + + min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof( struct liballoc_minor )); + + // Ensure it is a valid structure. + if ( min->magic != LIBALLOC_MAGIC ) + { + l_errorCount += 1; + + // Check for overrun errors. For all bytes of LIBALLOC_MAGIC + if ( + ((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || + ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || + ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF)) + ) + { + l_possibleOverruns += 1; + #if defined DEBUG || defined INFO + printf( "liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n", + min->magic, + LIBALLOC_MAGIC ); + FLUSH(); + #endif + } + + + if ( min->magic == LIBALLOC_DEAD ) + { + #if defined DEBUG || defined INFO + printf( "liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n", + ptr, + __builtin_return_address(0) ); + FLUSH(); + #endif + } + else + { + #if defined DEBUG || defined INFO + printf( "liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n", + ptr, + __builtin_return_address(0) ); + FLUSH(); + #endif + } + + // being lied to... + liballoc_unlock(); // release the lock + return NULL; + } + + // Definitely a memory block. + + real_size = min->req_size; + + if ( real_size >= size ) + { + min->req_size = size; + liballoc_unlock(); + return p; + } + + liballoc_unlock(); + + // If we got here then we're reallocating to a block bigger than us. + ptr = PREFIX(malloc)( size ); // We need to allocate new memory + liballoc_memcpy( ptr, p, real_size ); + PREFIX(free)( p ); + + return ptr; +} + diff --git a/chroma/system/memory/paging.c b/chroma/system/memory/paging.c index ed836c7..1ab92d5 100644 --- a/chroma/system/memory/paging.c +++ b/chroma/system/memory/paging.c @@ -34,26 +34,30 @@ void InitPaging() { .PML4 = PhysAllocateZeroMem(4096) }; - SerialPrintf("[ Mem] Identity mapping 2MB\r\n"); + SerialPrintf("[ Mem] Identity mapping the entirety of physical memory\r\n"); - for(size_t i = 0; i < 8192; i++) { + for(size_t i = 0; i < MemorySize / PAGE_SIZE; i++) { size_t Addr = i * 4096; MapVirtualPageNoDirect(&KernelAddressSpace, Addr, Addr, DEFAULT_PAGE_FLAGS); MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS); // TODO: Map kernel mem } + // This allows the code to actually run SerialPrintf("[ Mem] Mapping kernel\r\n"); - for(size_t i = KERNEL_PHYSICAL + KERNEL_TEXT; i < KERNEL_END; i += 4096) + for(size_t i = KERNEL_PHYSICAL + KERNEL_TEXT; i < KERNEL_END; i += PAGE_SIZE) MapVirtualPageNoDirect(&KernelAddressSpace, i, (i - KERNEL_PHYSICAL) + KERNEL_REGION, 0x3); + // This allows us to write to the screen SerialPrintf("[ Mem] Mapping framebuffer\r\n"); - for(size_t i = FB_PHYSICAL; i < bootldr.fb_size + FB_PHYSICAL; i += 4096) + for(size_t i = FB_PHYSICAL; i < bootldr.fb_size + FB_PHYSICAL; i += PAGE_SIZE) MapVirtualPageNoDirect(&KernelAddressSpace, i, (i - FB_PHYSICAL) + FB_REGION, 0x3); + // This allows us to call functions SerialPrintf("[ Mem] Mapping stack\r\n"); MapVirtualPageNoDirect(&KernelAddressSpace, CORE_STACK_PHYSICAL, STACK_TOP, 0x3); + // Make sure everything is sane SerialPrintf("[ Mem] Diagnostic: Querying existing page tables\r\n"); address_space_t BootloaderAddressSpace = (address_space_t) { .Lock = {0}, @@ -65,12 +69,12 @@ void InitPaging() { size_t KernelDisoveredAddress = DecodeVirtualAddressNoDirect(&KernelAddressSpace, AddressToFind); SerialPrintf("[ Mem] Diagnostic: Existing pagetables put 0x%p at 0x%p.\r\n", AddressToFind, BootloaderAddress); SerialPrintf("[ Mem] Diagnostic: Our pagetables put 0x%p at 0x%p.\r\n", AddressToFind, KernelDisoveredAddress); - SerialPrintf("[ Mem] %s\r\n", BootloaderAddress == KernelDisoveredAddress ? "These match. Continuing." : "These do not match. Halting.."); + SerialPrintf("[ Mem] %s\r\n", BootloaderAddress == KernelDisoveredAddress ? "These match. Continuing." : "These do not match. Continuing with caution.."); //if(BootloaderAddress != KernelDisoveredAddress) //for(;;) {} - SerialPrintf("[ Mem] Attempting to jump into our new pagetables: %d\r\n", (size_t) KernelAddressSpace.PML4); + SerialPrintf("[ Mem] Attempting to jump into our new pagetables: 0x%p\r\n", (size_t) KernelAddressSpace.PML4); WriteControlRegister(3, (size_t) KernelAddressSpace.PML4 & STACK_TOP); SerialPrintf("[ Mem] Worked\r\n"); for(;;) {} diff --git a/chroma/system/memory/physmem.c b/chroma/system/memory/physmem.c index 120d4f6..815d2e1 100644 --- a/chroma/system/memory/physmem.c +++ b/chroma/system/memory/physmem.c @@ -281,11 +281,11 @@ directptr_t PhysAllocateLowZeroMem(size_t Size) { } void PhysFreeMem(directptr_t Pointer, size_t Size) { - ASSERT(Pointer >= (directptr_t) DIRECT_REGION, "PhysFreeMem: Attempting to free memory not in the direct mapping region."); + //ASSERT(Pointer >= (directptr_t) DIRECT_REGION, "PhysFreeMem: Attempting to free memory not in the direct mapping region."); buddy_t* Buddy; - if(Pointer < (void*)(LOWER_REGION + DIRECT_REGION)) + if(Pointer < (void*)(LOWER_REGION /* + DIRECT_REGION */)) Buddy = &LowBuddy; else Buddy = &HighBuddy;