From 5ffa467b7d6f0eb11ecfcbae7db5e52b6926c7b3 Mon Sep 17 00:00:00 2001 From: Curle Date: Mon, 14 Jun 2021 01:36:46 +0100 Subject: [PATCH] Fix paging on >143MB ram. Add visual printf. --- chroma/inc/kernel/chroma.h | 3 +- chroma/inc/kernel/system/io.h | 1 + chroma/inc/kernel/system/memory.h | 3 +- chroma/kernel.c | 14 +++--- chroma/system/interrupts.c | 19 ++++---- chroma/system/memory/paging.c | 15 +++--- chroma/system/memory/physmem.c | 40 +++++++++------- chroma/video/draw.c | 23 +++++---- chroma/video/print.c | 79 +++++++++++++++++++++++++++++++ 9 files changed, 143 insertions(+), 54 deletions(-) diff --git a/chroma/inc/kernel/chroma.h b/chroma/inc/kernel/chroma.h index 6e5beff..3302392 100644 --- a/chroma/inc/kernel/chroma.h +++ b/chroma/inc/kernel/chroma.h @@ -52,7 +52,8 @@ typedef struct { size_t KernelAddr; size_t KernelEnd; size_t MemoryPages; -size_t MemorySize; +size_t FreeMemorySize; +size_t FullMemorySize; void DrawPixel(uint32_t x, uint32_t y, uint32_t color); diff --git a/chroma/inc/kernel/system/io.h b/chroma/inc/kernel/system/io.h index 00eaf64..2d7401f 100644 --- a/chroma/inc/kernel/system/io.h +++ b/chroma/inc/kernel/system/io.h @@ -73,6 +73,7 @@ void WriteSerialChar(const char); void WriteSerialString(const char*, size_t); int SerialPrintf(const char* restrict format, ...); +int Printf(const char* restrict Format, ...); void* memcpy(void* dest, void const* src, size_t len); void* memset(void* dst, int src, size_t len); \ No newline at end of file diff --git a/chroma/inc/kernel/system/memory.h b/chroma/inc/kernel/system/memory.h index 3888e57..56ec302 100644 --- a/chroma/inc/kernel/system/memory.h +++ b/chroma/inc/kernel/system/memory.h @@ -43,6 +43,7 @@ #define IS_ALIGNED(addr) (((size_t) addr | 0xFFFFFFFFFFFFF000) == 0) #define PAGE_ALIGN(addr) ((((size_t) addr) & 0xFFFFFFFFFFFFF000) + 0x1000) +#define PAGE_ALIGN_DOWN(addr) ((((size_t) addr) & 0xFFFFFFFFFFFFF000) - 0x1000) #define SET_PGBIT(cr0) (cr0 = cr0 | 1 << 31) #define UNSET_PGBIT(cr0) (cr0 = cr0 ^ 1 << 31) @@ -215,7 +216,7 @@ size_t AllocatorAllocateOverhead(void); size_t AlignUpwards(size_t Pointer, size_t Alignment); size_t AlignDownwards(size_t Pointer, size_t Alignment); -void* AlignPointer(const void* Pointer, size_t Alignment); +void* AlignPointer(const void* Pointer, size_t Alignment); /************************************************************ diff --git a/chroma/kernel.c b/chroma/kernel.c index a6bfba8..ac1a7a9 100644 --- a/chroma/kernel.c +++ b/chroma/kernel.c @@ -20,14 +20,14 @@ address_space_t KernelAddressSpace; int Main(void) { KernelAddressSpace = (address_space_t) {0}; - + SerialPrintf("\r\n[ boot] Booting Chroma..\r\n"); SerialPrintf("[ boot] Bootloader data structure at 0x%p\r\n", (size_t) &bootldr); SerialPrintf("[ boot] Kernel loaded at 0x%p, ends at 0x%p, is %d bytes long.\r\n", KernelAddr, KernelEnd, KernelEnd - KernelAddr); SerialPrintf("[ boot] Framebuffer at 0x%p / 0x%p, is %dx%d, 0x%x bytes long.\r\n", bootldr.fb_ptr, (size_t) &fb, bootldr.fb_width, bootldr.fb_height, bootldr.fb_size); SerialPrintf("[ boot] Initrd is physically at 0x%p, and is %d bytes long.\r\n", bootldr.initrd_ptr, bootldr.initrd_size); SerialPrintf("[ boot] Initrd's header is 0x%p\r\n", FIXENDIAN32(*((volatile uint32_t*)(bootldr.initrd_ptr)))); - + ParseKernelHeader(bootldr.initrd_ptr); SerialPrintf("[ boot] The bootloader has put the paging tables at 0x%p.\r\n", ReadControlRegister(3)); @@ -47,18 +47,16 @@ int Main(void) { InitMemoryManager(); //DrawSplash(); + InitPrint(); InitPaging(); - InitPrint(); + Printf("Paging complete. System initialized.\r\n"); - WriteString("Paging complete. System initialized."); - - - for(;;) { } + for (;;) {} return 0; - + } void SomethingWentWrong(const char* Message) { diff --git a/chroma/system/interrupts.c b/chroma/system/interrupts.c index 3548a2a..95df84b 100644 --- a/chroma/system/interrupts.c +++ b/chroma/system/interrupts.c @@ -206,7 +206,9 @@ void EmptyIRQ(INTERRUPT_FRAME* frame) { DrawPixel(x, y, 0x0000FF00); } } - + + for(size_t i = 0; i < 100000; i++) {} + for(size_t y = 0; y < bootldr.fb_height; y++) { for(size_t x = 0; x < 20; x++) { DrawPixel(x, y, 0x000000FF); @@ -257,14 +259,14 @@ void InitInterrupts() { /* The interrupt numbers, their meanings, and * special information is laid out below: - * + * * 0 - Divide by Zero * 1 - Debug * 2 - Non-Maskable * 3 - Breakpoint * 4 - Into Detected Overflow * 5 - Out of Bounds - * 6 - Invalid Opcode + * 6 - Invalid Opcode * 7 - No Coprocessor * 8 - Double Fault * (With Error) * 9 - Coprocessor Segment Overrun @@ -300,18 +302,19 @@ __attribute__((interrupt)) void ISR5Handler(INTERRUPT_FRAME* Frame) { ISR_Common(Frame, 5); } __attribute__((interrupt)) void ISR6Handler(INTERRUPT_FRAME* Frame) { - + __asm__ __volatile__("sti"); - + SerialPrintf("[FAULT] Invalid Opcode!\n"); size_t retAddr = 0; size_t opcodeAddr = Frame->rip; __asm__ __volatile__("popq %%rax\n\t" "pushq %%rax": "=a" (retAddr) : :); SerialPrintf("[FAULT] Opcode is at 0x%x, called from 0x%p\r\n", opcodeAddr, retAddr); - + Printf("Invalid Opcode: 0x%p\n", opcodeAddr); + StackTrace(15); - + for(;;) {} } __attribute__((interrupt)) void ISR7Handler(INTERRUPT_FRAME* Frame) { @@ -357,7 +360,7 @@ __attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t Erro if(FaultReserved) SerialPrintf("[FAULT] Overwrote reserved bits.\r\n"); if(FaultInst) SerialPrintf("[FAULT] \"Instruction Fetch\""); - SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2)); + SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2)); StackTrace(6); ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault diff --git a/chroma/system/memory/paging.c b/chroma/system/memory/paging.c index 7ba1ef2..db4aad7 100644 --- a/chroma/system/memory/paging.c +++ b/chroma/system/memory/paging.c @@ -44,9 +44,9 @@ void InitPaging() { KernelLocation = DecodeVirtualAddressNoDirect(&BootloaderAddressSpace, AddressToFind); SerialPrintf("[ Mem] Double check: Kernel physically starts at 0x%p (0x%p), ends at 0x%p.\r\n", KernelLocation, AddressToFind, KERNEL_END); - SerialPrintf("[ Mem] Identity mapping the entirety of physical memory\r\n"); + SerialPrintf("[ Mem] Identity mapping the entire 0x%p bytes of physical memory to 0x%p\r\n", FullMemorySize, (size_t) KernelAddressSpace.PML4); - for(size_t i = 0; i < MemorySize / PAGE_SIZE; i++) { + for(size_t i = 0; i < (FullMemorySize / 4096); i++) { size_t Addr = i * 4096; MapVirtualPageNoDirect(&KernelAddressSpace, Addr, Addr, DEFAULT_PAGE_FLAGS); MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS); @@ -82,9 +82,6 @@ void InitPaging() { SerialPrintf("[ Mem] Diagnostic: Existing pagetables put 0x%p at 0x%p + 0x%p.\r\n", AddressToFind, KERNEL_PHYSICAL, AddressToFind & ~STACK_TOP); SerialPrintf("[ Mem] %s\r\n", KernelAddress == KERNEL_PHYSICAL ? "These match. Continuing." : "These do not match. Continuing with caution.."); - //if(BootloaderAddress != KernelDisoveredAddress) - //for(;;) {} - 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"); @@ -266,6 +263,7 @@ void MapVirtualPageNoDirect(address_space_t* AddressSpace, size_t Physical, size AddressSpace->PML4[PDPT] = (size_t) PDPT_T | DEFAULT_PAGE_FLAGS; } + // The above repeats. if(PDPT_T[PDP] & PRESENT_BIT) PDE_T = (size_t*) (PDPT_T[PDP] & STACK_TOP); @@ -274,6 +272,7 @@ void MapVirtualPageNoDirect(address_space_t* AddressSpace, size_t Physical, size PDPT_T[PDP] = (size_t) PDE_T | DEFAULT_PAGE_FLAGS; } + if(PDE_T[PDE] & PRESENT_BIT) PT_T = (size_t*) (PDE_T[PDE] & STACK_TOP); else { @@ -281,8 +280,9 @@ void MapVirtualPageNoDirect(address_space_t* AddressSpace, size_t Physical, size PDE_T[PDE] = (size_t) PT_T | DEFAULT_PAGE_FLAGS; } - // Finally, set the last page table content to the physical page + the flags we specified. - PT_T[PT] = (size_t) (Physical | PageFlags); + // Finally, set the last page table content to the physical page + the flags we specified.] + *(PT_T + PT) = (size_t) (Physical | PageFlags); + } /** @@ -318,7 +318,6 @@ size_t* CreateNewPageTable(address_space_t* AddressSpace) { MapVirtualPage(&TempAddressSpace, Addr, Addr, DEFAULT_PAGE_FLAGS); // Map higher half MapVirtualPage(&TempAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS); - // TODO: Map into kernel space } // Identity map the next 4gb diff --git a/chroma/system/memory/physmem.c b/chroma/system/memory/physmem.c index 815d2e1..76b062f 100644 --- a/chroma/system/memory/physmem.c +++ b/chroma/system/memory/physmem.c @@ -11,16 +11,16 @@ * * This is also called blocking, or block memory allocation. * It mostly deals with the memory map handed to us by the bootloader. - * + * * It is useful in virtual memory management, because it allows us to map one block of physical memory to one page of virtual memory. - * + * * Most of the processing here is done with a bitwise mapping of blocks to allocations, normally called a memory bitmap. * See heap.h for the implementation. - * + * * This file also contains memory manipulation functions, like memset and memcpy. * //TODO: replace these functions with SSE2 equivalent. - * - */ + * + */ #define MIN_ORDER 3 @@ -77,7 +77,7 @@ static void AddToBuddyList(buddy_t* Buddy, directptr_t Address, size_t Order, bo if(CheckBuddies(Buddy, ListHead, Address, Size)) { if(ListPrevious != 0) { PEEK(directptr_t, ListPrevious) = PEEK(directptr_t, ListHead); - } else + } else Buddy->List[Order - MIN_ORDER] = PEEK(directptr_t, ListHead); AddToBuddyList(Buddy, MIN(ListHead, Address), Order + 1, false); @@ -136,7 +136,7 @@ static directptr_t BuddyAllocate(buddy_t* Buddy, size_t Size) { TicketAttemptLock(&Buddy->Lock); //SerialPrintf("Searching for a valid order to allocate into. Condition: {\r\n\tOrder: %d,\r\n\tSize: 0x%x\r\n}\r\n\n", InitialOrder, WantedSize); - + for(int Order = InitialOrder; Order < Buddy->MaxOrder; Order++) { //SerialPrintf("\tCurrent Order: %d, Buddy entry: %x\r\n", Order, Buddy->List[Order - MIN_ORDER]); if(Buddy->List[Order - MIN_ORDER] != 0) { @@ -146,7 +146,7 @@ static directptr_t BuddyAllocate(buddy_t* Buddy, size_t Size) { TicketUnlock(&Buddy->Lock); size_t FoundSize = 1ull << Order; - + //SerialPrintf("\tAdding area - Address 0x%p, Size 0x%x\r\n\n", Address, FoundSize); AddRangeToBuddy(Buddy, (void*)((size_t)Address + WantedSize), FoundSize - WantedSize); @@ -166,24 +166,26 @@ void InitMemoryManager() { SerialPrintf("[ Mem] Counting memory..\r\n"); - MemorySize = 0; + FreeMemorySize = 0; + FullMemorySize = 0; size_t MemMapEntryCount = 0; MMapEnt* MemMap = &bootldr.mmap; while((size_t) MemMap < ((size_t) &bootldr) + bootldr.size) { if(MMapEnt_IsFree(MemMap)) { - MemorySize += MMapEnt_Size(MemMap); + FreeMemorySize += MMapEnt_Size(MemMap); } + FullMemorySize += MMapEnt_Size(MemMap); MemMapEntryCount++; MemMap++; } SerialPrintf("[ Mem] Counted %d entries in the memory map..\r\n", MemMapEntryCount); - MemoryPages = MemorySize / PAGE_SIZE; + MemoryPages = FreeMemorySize / PAGE_SIZE; - SerialPrintf("[ Mem] %u MB of memory detected.\r\n", (MemorySize / 1024) / 1024); + SerialPrintf("[ Mem] %u MB of memory detected.\r\n", (FreeMemorySize / 1024) / 1024); } @@ -217,8 +219,14 @@ void ListMemoryMap() { SerialPrintf("[ Mem] 0x%p-0x%p %s\r\n", entry_from, entry_to, EntryType); if(MMapEnt_Type(MapEntry) == MMAP_FREE) { - SerialPrintf("[ Mem] Adding this entry to the physical memory manager!\r\n"); - AddRangeToPhysMem((void*)((char*)(MMapEnt_Ptr(MapEntry) /* + DIRECT_REGION*/ )), MMapEnt_Size(MapEntry)); + // We need to page align the inputs to the buddy lists. + size_t page_from = AlignUpwards(entry_from, 0x1000); + size_t page_to = AlignDownwards(entry_to, 0x1000); + + if(page_from != 0 && page_to != 0) { + SerialPrintf("[ Mem] Adding the range 0x%p-0x%p to the physical memory manager!\r\n", page_from, page_to); + AddRangeToPhysMem((void*)((char*)(page_from)), page_to - page_from); + } } } @@ -261,7 +269,7 @@ directptr_t PhysAllocateMem(size_t Size) { //SerialPrintf("Attempting allocation into low memory.\n"); Pointer = BuddyAllocate(&LowBuddy, Size); } - + ASSERT(Pointer != NULL, "PhysAllocateMem: Unable to allocate memory!"); return Pointer; @@ -289,7 +297,7 @@ void PhysFreeMem(directptr_t Pointer, size_t Size) { Buddy = &LowBuddy; else Buddy = &HighBuddy; - + int Order = MAX(64 - CLZ(Size - 1), MIN_ORDER); AddToBuddyList(Buddy, Pointer, Order, false); } diff --git a/chroma/video/draw.c b/chroma/video/draw.c index 9575548..4e5cd7d 100644 --- a/chroma/video/draw.c +++ b/chroma/video/draw.c @@ -54,18 +54,20 @@ void InitPrint() { PrintInfo.charHLColor = 0x00000000; PrintInfo.charBGColor = 0x00000000; - PrintInfo.charScale = 2; + PrintInfo.charScale = 1; - PrintInfo.charPosX = 0; - PrintInfo.charPosY = 1; + PrintInfo.charPosX = 1; + PrintInfo.charPosY = 2; PrintInfo.scrlMode = 0; - PrintInfo.charsPerRow = bootldr.fb_width / (PrintInfo.charScale * PrintInfo.charWidth) - 5; + PrintInfo.charsPerRow = bootldr.fb_width / (PrintInfo.charScale * PrintInfo.charWidth) - 4; PrintInfo.rowsPerScrn = bootldr.fb_height / (PrintInfo.charScale * PrintInfo.charHeight); SerialPrintf("[Print] A single character is %ux%u pixels.\r\n", PrintInfo.charScale * PrintInfo.charWidth, PrintInfo.charScale * PrintInfo.charHeight); SerialPrintf("[Print] The screen is %ux%u, meaning you can fit %ux%u characters on screen.\r\n", bootldr.fb_width, bootldr.fb_height, PrintInfo.charsPerRow, PrintInfo.rowsPerScrn); + WriteString("Testing print\n"); + } static void DrawChar(const char character, size_t x, size_t y) { @@ -91,12 +93,10 @@ static void DrawChar(const char character, size_t x, size_t y) { if((FONT[(int)character][Row * Y + X] >> (Bit & 0x7)) & 1) { // Check the bit in the bitmap, if it's solid.. for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { // Take care of the scale height for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { // And the scale width - size_t offset = ((y * bootldr.fb_width + x) + // Calculate the offset from the framebuffer PrintInfo.charScale * (Row * bootldr.fb_width + Bit) + // With the appropriate scale (ScaleY * bootldr.fb_width + ScaleX) + // In X and Y PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; // With some offset to start at 0 - *(uint32_t* )(&fb + offset * 4) // And use it to set the correct pixel on the screen = PrintInfo.charFGColor; // In the set foreground color } @@ -277,7 +277,6 @@ void WriteChar(const char character) { break; default: DrawChar(character, PrintInfo.charPosX, PrintInfo.charPosY); - ProgressCursor(); break; } @@ -299,11 +298,11 @@ void WriteStringWithFont(const char *inChar) const unsigned int bytesPerLine = ( font -> glyphWidth + 7 ) / 8; while(*inChar) { - unsigned char *glyph = + unsigned char *glyph = (unsigned char*) &_binary_font_psf_start - + font->headerSize - + (*inChar > 0 && *inChar < (int)font->numGlyphs ? *inChar : 0) * - font->glyphSize; + + font->headerSize + + (*inChar > 0 && *inChar < (int)font->numGlyphs ? *inChar : 0) + * font->glyphSize; offset = (kx * (font->glyphWidth + 1) * 4); @@ -311,7 +310,7 @@ void WriteStringWithFont(const char *inChar) for( drawY = 0; drawY < font->glyphHeight ; drawY++) { fontLine = offset; bitMask = 1 << (font->glyphWidth - 1); - + for( drawX = 0; drawX < font->glyphWidth; drawX++) { *((uint32_t*)((uint64_t) &fb + fontLine)) = diff --git a/chroma/video/print.c b/chroma/video/print.c index d7146b7..01aeeaa 100644 --- a/chroma/video/print.c +++ b/chroma/video/print.c @@ -120,3 +120,82 @@ int SerialPrintf(const char* restrict Format, ...) { return CharsWritten; } +int Printf(const char* restrict Format, ...) { + va_list Parameters; + va_start(Parameters, Format); + + int CharsWritten = 0; + size_t Base, Num; + + char BufferStr[512] = {0}; + + while(*Format != '\0') { + size_t Limit = UINT64_MAX - CharsWritten; + + if(*Format == '%') { + if(*(++Format) == '%') + Format++; + + switch(*Format) { + case 'c': + Format++; + + char c = (char) va_arg(Parameters, int); + + WriteString(&c); + + CharsWritten++; + break; + case 's': + Format++; + const char* Str = va_arg(Parameters, char*); + + size_t Len = strlen(Str); + + if(Limit < Len) + return -1; + + WriteString(Str); + + CharsWritten += Len; + break; + case 'd': + case 'u': + case 'p': + case 'x': + + Num = va_arg(Parameters, size_t); + Base = 0; + + + if(*Format == 'd' || *Format == 'u') { + Base = 10; // Decimal & Unsigned are base 10 + } else { + Base = 16; // Hex and Ptr are base 16 + } + Format++; + + NumToStr(BufferStr, Num, Base); + Len = strlen(BufferStr); + + WriteString(BufferStr); + + CharsWritten += Len; + break; + //case 'p': + //uint8_t Base = 16; + //size_t Dest = (uintptr_t) va_arg(Parameters, void*); + default: + WriteString("%u"); + break; + } + + } else { + WriteChar(*Format); + Format++; + } + } + + va_end(Parameters); + return CharsWritten; +}