From d8b11d2074b48f17f999d44c75b1f76fdffd970b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 28 May 2010 19:58:44 +0800 Subject: [PATCH] Fixes to 64-bit port, now working on physical memory allocation --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86_64/desctab.asm | 2 +- Kernel/arch/x86_64/include/arch.h | 5 +- Kernel/arch/x86_64/include/mm_virt.h | 23 +++--- Kernel/arch/x86_64/main.c | 52 +++++++++++- Kernel/arch/x86_64/mm_phys.c | 115 ++++++++++++++++++++++++--- Kernel/arch/x86_64/mm_virt.c | 4 + Kernel/arch/x86_64/start32.asm | 21 +++-- Kernel/arch/x86_64/start64.asm | 6 ++ Kernel/heap.c | 2 +- 10 files changed, 195 insertions(+), 37 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index fe15723c..4e90b47c 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 2243 +BUILD_NUM = 2263 diff --git a/Kernel/arch/x86_64/desctab.asm b/Kernel/arch/x86_64/desctab.asm index d49dbc43..039fe95e 100644 --- a/Kernel/arch/x86_64/desctab.asm +++ b/Kernel/arch/x86_64/desctab.asm @@ -293,7 +293,7 @@ IrqCommon: POP_GPR add rsp, 8*2 - xchg bx, bx + ;xchg bx, bx iretq [extern Proc_Scheduler] diff --git a/Kernel/arch/x86_64/include/arch.h b/Kernel/arch/x86_64/include/arch.h index 0dc99277..5ea3d886 100644 --- a/Kernel/arch/x86_64/include/arch.h +++ b/Kernel/arch/x86_64/include/arch.h @@ -28,16 +28,15 @@ typedef Uint64 Uint; typedef Uint64 tPAddr; typedef Uint64 tVAddr; -//typedef unsigned int size_t; typedef Uint64 size_t; typedef volatile int tSpinlock; #define IS_LOCKED(lockptr) (!!(*(tSpinlock*)lockptr)) #define LOCK(lockptr) do {int v=1;\ while(v)\ - __asm__ __volatile__("lock xchgl %%eax, (%%rdi)":"=a"(v):"a"(1),"D"(lockptr));\ + __asm__ __volatile__("lock xchgl %0, (%2)":"=r"(v):"r"(1),"r"(lockptr));\ }while(0) -#define RELEASE(lockptr) __asm__ __volatile__("lock andl $0, (%%rdi)"::"D"(lockptr)); +#define RELEASE(lockptr) __asm__ __volatile__("lock andl $0, (%0)"::"r"(lockptr)); #define HALT() __asm__ __volatile__ ("hlt") // Systemcall Registers diff --git a/Kernel/arch/x86_64/include/mm_virt.h b/Kernel/arch/x86_64/include/mm_virt.h index 502be559..206dcd93 100644 --- a/Kernel/arch/x86_64/include/mm_virt.h +++ b/Kernel/arch/x86_64/include/mm_virt.h @@ -25,9 +25,11 @@ * 9000 00000000 - 9800 00000000 43 8 TiB Module Space * 9800 00000000 - 9A00 00000000 41 2 TiB Kernel VFS * A000 00000000 - B000 00000000 44 16 TiB Kernel Stacks - * D000 00000000 - E000 00000000 44 16 TiB Hardware Mappings - * E000 00000000 - E080 00000000 39 512 GiB Per-Process Data - * E080 00000000 - E100 00000000 39 512 GiB Kernel Supplied User Code + * C000 00000000 - D000 00000000 44 16 TiB Hardware Mappings + * D000 00000000 - D080 00000000 39 512 GiB Per-Process Data + * D080 00000000 - D100 00000000 39 512 GiB Kernel Supplied User Code + * E000 00000000 - E400 00000000 42 4 TiB Physical Page Reference Counts (2**40 = 2**52 bytes) + * FD00 00000000 - FD80 00000000 39 512 GiB Local APIC * FE00 00000000 - FE80 00000000 39 512 GiB Fractal Mapping (PML4 510) * FE80 00000000 - FF00 00000000 39 512 GiB Temp Fractal Mapping */ @@ -39,19 +41,20 @@ #define MM_USER_MAX 0x00008FFF##FFFFF000 //#define KERNEL_BASE 0xFFF8000##00000000 #define MM_KHEAP_BASE (KERNEL_BASE|(0x8000##80000000)) -#define MM_KHEAP_MAX (KERNEL_BASE|(0x8001##00000000)) +#define MM_KHEAP_MAX (KERNEL_BASE|(0x9000##00000000)) #define MM_MODULE_MIN (KERNEL_BASE|(0x9000##00000000)) #define MM_MODULE_MAX (KERNEL_BASE|(0x9800##00000000)) #define MM_KERNEL_VFS (KERNEL_BASE|(0x9800##00000000)) #define MM_KSTACK_BASE (KERNEL_BASE|(0xA000##00000000)) -#define MM_KSTACK_TOP (KERNEL_BASE|(0xC000##00000000)) +#define MM_KSTACK_TOP (KERNEL_BASE|(0xB000##00000000)) -#define MM_HWMAP_BASE (KERNEL_BASE|(0xD000##00000000)) -#define MM_HWMAP_TOP (KERNEL_BASE|(0xE000##00000000)) -#define MM_PPD_BASE (KERNEL_BASE|(0xE000##00000000)) +#define MM_HWMAP_BASE (KERNEL_BASE|(0xC000##00000000)) +#define MM_HWMAP_TOP (KERNEL_BASE|(0xD000##00000000)) +#define MM_PPD_BASE (KERNEL_BASE|(0xD000##00000000)) #define MM_PPD_CFG MM_PPD_BASE -#define MM_PPD_VFS (KERNEL_BASE|(0xE008##00000000)) -#define MM_USER_CODE (KERNEL_BASE|(0xE080##00000000)) +#define MM_PPD_VFS (KERNEL_BASE|(0xD008##00000000)) +#define MM_USER_CODE (KERNEL_BASE|(0xD080##00000000)) +#define MM_PAGE_COUNTS (KERNEL_BASE|(0xE000##00000000)) #define MM_LOCALAPIC (KERNEL_BASE|(0xFD00##00000000)) #define MM_FRACTAL_BASE (KERNEL_BASE|(0xFE00##00000000)) diff --git a/Kernel/arch/x86_64/main.c b/Kernel/arch/x86_64/main.c index 8dfd1771..6388d1bf 100644 --- a/Kernel/arch/x86_64/main.c +++ b/Kernel/arch/x86_64/main.c @@ -2,28 +2,72 @@ * Acess2 x86_64 Project */ #include +#include // === IMPORTS === extern void Desctab_Init(void); extern void MM_InitVirt(void); +extern void Heap_Install(void); +extern void Threads_Init(void); +//extern void Time_Setup(void); +extern void System_Init(char *Commandline); + +extern void MM_InitPhys_Multiboot(tMBoot_Info *MBoot); // === PROTOTYPES === // === GLOBALS == +char *gsBootCmdLine = NULL; // === CODE === void kmain(Uint MbMagic, void *MbInfoPtr) { - *(Uint16*)(0xB8000) = 0x1F00|'A'; + tMBoot_Info *mbInfo; Desctab_Init(); - *(Uint16*)(0xB8000) = 0x1F00|'B'; MM_InitVirt(); - *(Uint16*)(0xB8000) = 0x1F00|'B'; + *(Uint16*)(0xB8000) = 0x1F00|'C'; + + switch(MbMagic) + { + // Multiboot 1 + case MULTIBOOT_MAGIC: + // Adjust Multiboot structure address + mbInfo = (void*)( (Uint)MbInfoPtr + KERNEL_BASE ); + gsBootCmdLine = (char*)(mbInfo->CommandLine + KERNEL_BASE); + + MM_InitPhys_Multiboot( mbInfo ); // Set up physical memory manager + break; + default: + Panic("Multiboot magic invalid %08x, expected %08x\n", + MbMagic, MULTIBOOT_MAGIC); + return ; + } + + *(Uint16*)(0xB8000) = 0x1F00|'D'; + Heap_Install(); + + *(Uint16*)(0xB8000) = 0x1F00|'E'; + Log_Log("Arch", "Starting threading..."); + Threads_Init(); + + //Time_Setup(); + *(Uint16*)(0xB8000) = 0x1F00|'F'; + + Log_Log("Arch", "Starting VFS..."); + // Load Virtual Filesystem + VFS_Init(); + + *(Uint16*)(0xB8000) = 0x1F00|'G'; + + // Pass on to Independent Loader + Log_Log("Arch", "Starting system"); + System_Init(gsBootCmdLine); + // Sleep forever (sleeping beauty) for(;;) - __asm__ __volatile__ ("hlt"); + Threads_Sleep(); } void Arch_LoadBootModules(void) diff --git a/Kernel/arch/x86_64/mm_phys.c b/Kernel/arch/x86_64/mm_phys.c index dd8ddf66..5a5f5eab 100644 --- a/Kernel/arch/x86_64/mm_phys.c +++ b/Kernel/arch/x86_64/mm_phys.c @@ -5,7 +5,7 @@ */ #include #include -//#include +#include enum eMMPhys_Ranges { @@ -17,11 +17,13 @@ enum eMMPhys_Ranges NUM_MM_PHYS_RANGES }; +// === IMPORTS === +extern void gKernelEnd; + // === GLOBALS === tSpinlock glPhysicalPages; Uint64 *gaSuperBitmap; // 1 bit = 64 Pages -Uint64 *gaPrimaryBitmap; // 1 bit = 64 Pages -Uint32 *gaiPageReferences; // Reference Counts +Uint32 *gaiPageReferences = (void*)MM_PAGE_COUNTS; // Reference Counts tPAddr giFirstFreePage; // First possibly free page Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each range Uint64 giPhysRangeFirst[NUM_MM_PHYS_RANGES]; // First free page in each range @@ -29,33 +31,95 @@ Uint64 giPhysRangeLast[NUM_MM_PHYS_RANGES]; // Last free page in each range Uint64 giMaxPhysPage = 0; // Maximum Physical page // === CODE === -void MM_InitPhys(tMBoot_Info *MBoot) +void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) { tMBoot_MMapEnt *mmapStart; tMBoot_MMapEnt *ent; Uint64 maxAddr = 0; + int numPages; + + Log("MM_InitPhys_Multiboot: (MBoot=%p)", MBoot); // Scan the physical memory map + // Looking for the top of physical memory mmapStart = (void *)( KERNEL_BASE | MBoot->MMapAddr ); + Log(" MM_InitPhys_Multiboot: mmapStart = %p", mmapStart); ent = mmapStart; while( (Uint)ent < (Uint)mmapStart + MBoot->MMapLength ) { // Adjust for the size of the entry ent->Size += 4; + Log(" MM_InitPhys_Multiboot: ent={Type:%i,Base:0x%x,Length:%x", + ent->Type, ent->Base, ent->Length); // If entry is RAM and is above `maxAddr`, change `maxAddr` if(ent->Type == 1 && ent->Base + ent->Length > maxAddr) maxAddr = ent->Base + ent->Length; + // Go to next entry ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ); } + // Did we find a valid end? if(maxAddr == 0) { + // No, darn, let's just use the HighMem hack giMaxPhysPage = (MBoot->HighMem >> 2) + 256; // HighMem is a kByte value } else { + // Goodie, goodie gumdrops giMaxPhysPage = maxAddr >> 12; } + Log(" MM_InitPhys_Multiboot: giMaxPhysPage = 0x%x", giMaxPhysPage); + + // Find a contigous section of memory to hold it in + // - Starting from the end of the kernel + // - We also need a region for the super bitmap + numPages = (giMaxPhysPage + 7) * sizeof(*gaiPageReferences); + numPages = (numPages + 0xFFF) >> 12; + Log(" MM_InitPhys_Multiboot: numPages = %i", numPages); + if(maxAddr == 0) + { + // Ok, naieve allocation, just put it after the kernel + tVAddr vaddr = MM_PAGE_COUNTS; + tPAddr paddr = (tPAddr)&gKernelEnd - KERNEL_BASE; + while(numPages --) + { + MM_Map(vaddr, paddr); + vaddr += 0x1000; + paddr += 0x1000; + } + // Allocate the super bitmap + gaSuperBitmap = (void*) MM_MapHWPages( + paddr, + ((giMaxPhysPage+64*8-1)/(64*8) + 0xFFF) >> 12 + ); + } + // Scan for a nice range + else + { + + } + + // Fill the bitmaps + // - initialise to one, then clear the avaliable areas + memset(gaSuperBitmap, -1, (giMaxPhysPage+64*8-1)/(64*8)); + memset(gaiPageReferences, -1, giMaxPhysPage*sizeof(*gaiPageReferences)); + // - Clear all Type=1 areas + for( + ent = mmapStart; + (Uint)ent < (Uint)mmapStart + MBoot->MMapLength; + ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ) + ) + { + // Check if the type is RAM + if(ent->Type != 1) continue; + // Clear the range + memset( + &gaiPageReferences[ ent->Base >> 12 ], + 0, + (ent->Size>>12)*sizeof(*gaiPageReferences) + ); + } } /** @@ -72,6 +136,8 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) int rangeID; int nFree = 0, i; + Log("MM_AllocPhysRange: (Num=%i,Bits=%i)", Num, Bits); + if( Bits <= 0 ) // Speedup for the common case rangeID = MM_PHYS_MAX; else if( Bits > 32 ) @@ -85,17 +151,23 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) else rangeID = MM_PHYS_16BIT; + Log(" MM_AllocPhysRange: rangeID = %i", rangeID); + LOCK(&glPhysicalPages); + Log(" MM_AllocPhysRange: i has lock"); // Check if the range actually has any free pages while(giPhysRangeFree[rangeID] == 0 && rangeID) rangeID --; + Log(" MM_AllocPhysRange: rangeID = %i", rangeID); + // What the? Oh, man. No free pages if(giPhysRangeFree[rangeID] == 0) { RELEASE(&glPhysicalPages); // TODO: Page out // ATM. Just Warning + Warning(" MM_AllocPhysRange: Out of free pages"); Log_Warning("Arch", "Out of memory (unable to fulfil request for %i pages), zero remaining", Num @@ -148,6 +220,7 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) // until a free range is found) nFree = 1; addr = giPhysRangeLast[ rangeID ]; + // TODO RELEASE(&glPhysicalPages); // TODO: Page out // ATM. Just Warning @@ -157,15 +230,13 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) ); return 0; } + Log(" MM_AllocPhysRange: nFree = %i, addr = 0x%08x", nFree, addr); // Mark pages as allocated addr -= Num; for( i = 0; i < Num; i++ ) { gaiPageReferences[addr] = 1; - gaPrimaryBitmap[addr>>6] |= 1 << (addr & 63); - if( gaPrimaryBitmap[addr>>6] == -1 ) - gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64); if(addr >> 32) rangeID = MM_PHYS_MAX; else if(addr >> 24) rangeID = MM_PHYS_32BIT; @@ -174,9 +245,25 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) else if(addr >> 0) rangeID = MM_PHYS_16BIT; giPhysRangeFree[ rangeID ] --; } + // Fill super bitmap + Num += addr & (64-1); + addr &= ~(64-1); + Num = (Num + (64-1)) & ~(64-1); + for( i = 0; i < Num/64; i++ ) + { + int j, bFull = 1; + for( j = 0; j < 64; j ++ ) { + if( gaiPageReferences[addr+i*64+j] ) { + bFull = 0; + break; + } + } + if( bFull ) + gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64); + } RELEASE(&glPhysicalPages); - return addr; + return addr << 12; } /** @@ -193,11 +280,18 @@ tPAddr MM_AllocPhys(void) */ void MM_RefPhys(tPAddr PAddr) { + int bIsFull, j; if( PAddr >> 12 > giMaxPhysPage ) return ; gaiPageReferences[ PAddr >> 12 ] ++; - gaPrimaryBitmap[PAddr >> 18] |= 1 << ((PAddr>>12) & 63); - if( gaPrimaryBitmap[PAddr >> 18] == -1 ) + bIsFull = 1; + for( j = 0; j < 64; j++ ) { + if( gaiPageReferences[ PAddr >> 12 ] == 0 ) { + bIsFull = 0; + break; + } + } + if( bIsFull ) gaSuperBitmap[PAddr >> 24] |= 1 << ((PAddr >> 18) & 64); } @@ -210,7 +304,6 @@ void MM_DerefPhys(tPAddr PAddr) gaiPageReferences[ PAddr >> 12 ] --; if( gaiPageReferences[ PAddr >> 12 ] ) { - gaPrimaryBitmap[PAddr >> 18] &= ~(1 << ((PAddr >> 12) & 63)); gaSuperBitmap[PAddr >> 24] &= ~(1 << ((PAddr >> 18) & 64)); } } diff --git a/Kernel/arch/x86_64/mm_virt.c b/Kernel/arch/x86_64/mm_virt.c index f1a4a800..1a70d3e7 100644 --- a/Kernel/arch/x86_64/mm_virt.c +++ b/Kernel/arch/x86_64/mm_virt.c @@ -105,11 +105,15 @@ tPAddr MM_Allocate(tVAddr VAddr) { tPAddr ret; + Log("MM_Allocate: (VAddr=%x)", VAddr); + Log("MM_Allocate: MM_AllocPhys()"); ret = MM_AllocPhys(); + Log("MM_Allocate: ret = %x", ret); if(!ret) return 0; if( !MM_Map(VAddr, ret) ) { + Warning("MM_Allocate: Unable to map", ret); MM_DerefPhys(ret); return 0; } diff --git a/Kernel/arch/x86_64/start32.asm b/Kernel/arch/x86_64/start32.asm index 6f3c9a77..7983d2c0 100644 --- a/Kernel/arch/x86_64/start32.asm +++ b/Kernel/arch/x86_64/start32.asm @@ -32,6 +32,9 @@ mboot: [section .text] [global start] start: + mov [gMultibootMagic - KERNEL_BASE], eax + mov [gMultibootPtr - KERNEL_BASE], ebx + ; Check for Long Mode support mov eax, 0x80000000 cpuid @@ -85,17 +88,23 @@ start: [global gGDT] gGDT: dd 0,0 - dd 0x00000000, 0x00209800 ; 0x08: 64-bit Code - dd 0x00000000, 0x00009000 ; 0x10: 64-bit Data - dd 0x00000000, 0x00209800 ; 0x18: 64-bit User Code - dd 0x00000000, 0x00209000 ; 0x20: 64-bit User Data - dd 0x00000000, 0x00209800 ; 0x38: 32-bit User Code - dd 0x00000000, 0x00209000 ; 0x30: 32-bit User Data + dd 0x00000000, 0x00209A00 ; 0x08: 64-bit Code + dd 0x00000000, 0x00009200 ; 0x10: 64-bit Data + dd 0x00000000, 0x0020FA00 ; 0x18: 64-bit User Code + dd 0x00000000, 0x0000F200 ; 0x20: 64-bit User Data + dd 0x00000000, 0x0040FA00 ; 0x38: 32-bit User Code + dd 0x00000000, 0x0040F200 ; 0x30: 32-bit User Data times MAX_CPUS dd 0, 0, 0, 0 ; 0x38+16*n: TSS 0 gGDTPtr: dw $-gGDT-1 dd gGDT-KERNEL_BASE dd 0 +[global gMultibootPtr] +[global gMultibootMagic] +gMultibootMagic: + dd 0 +gMultibootPtr: + dd 0 [section .padata] [global gInitialPML4] diff --git a/Kernel/arch/x86_64/start64.asm b/Kernel/arch/x86_64/start64.asm index 9302c052..04bac269 100644 --- a/Kernel/arch/x86_64/start64.asm +++ b/Kernel/arch/x86_64/start64.asm @@ -2,9 +2,13 @@ ; Acess2 x86_64 Port ; [bits 64] +KERNEL_BASE equ 0xFFFF800000000000 [extern kmain] +[extern gMultibootPtr] +[extern gMultibootMagic] + [section .text] [global start64] start64: @@ -30,6 +34,8 @@ start64: mov rsp, gInitialKernelStack ; Call main + mov edi, [gMultibootMagic - KERNEL_BASE] + mov esi, [gMultibootPtr - KERNEL_BASE] call kmain cli diff --git a/Kernel/heap.c b/Kernel/heap.c index 9d282b98..8ceefac1 100644 --- a/Kernel/heap.c +++ b/Kernel/heap.c @@ -30,7 +30,7 @@ void free(void *Ptr); void Heap_Dump(); // === GLOBALS === - int glHeap; +tSpinlock glHeap; void *gHeapStart; void *gHeapEnd; -- 2.20.1