Fixes to 64-bit port, now working on physical memory allocation
authorJohn Hodge <[email protected]>
Fri, 28 May 2010 11:58:44 +0000 (19:58 +0800)
committerJohn Hodge <[email protected]>
Fri, 28 May 2010 11:58:44 +0000 (19:58 +0800)
Kernel/Makefile.BuildNum
Kernel/arch/x86_64/desctab.asm
Kernel/arch/x86_64/include/arch.h
Kernel/arch/x86_64/include/mm_virt.h
Kernel/arch/x86_64/main.c
Kernel/arch/x86_64/mm_phys.c
Kernel/arch/x86_64/mm_virt.c
Kernel/arch/x86_64/start32.asm
Kernel/arch/x86_64/start64.asm
Kernel/heap.c

index fe15723..4e90b47 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 2243
+BUILD_NUM = 2263
index d49dbc4..039fe95 100644 (file)
@@ -293,7 +293,7 @@ IrqCommon:
        
        POP_GPR
        add rsp, 8*2
-       xchg bx, bx
+       ;xchg bx, bx
        iretq
 
 [extern Proc_Scheduler]
index 0dc9927..5ea3d88 100644 (file)
@@ -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
index 502be55..206dcd9 100644 (file)
  *       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
  */
 #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))
index 8dfd177..6388d1b 100644 (file)
@@ -2,28 +2,72 @@
  * Acess2 x86_64 Project
  */
 #include <acess.h>
+#include <mboot.h>
 
 // === 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)
index dd8ddf6..5a5f5ea 100644 (file)
@@ -5,7 +5,7 @@
  */
 #include <acess.h>
 #include <mboot.h>
-//#include <mm_phys.h>
+#include <mm_virt.h>
 
 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));
        }
 }
index f1a4a80..1a70d3e 100644 (file)
@@ -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;
        }
index 6f3c9a7..7983d2c 100644 (file)
@@ -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]
index 9302c05..04bac26 100644 (file)
@@ -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
index 9d282b9..8ceefac 100644 (file)
@@ -30,7 +30,7 @@ void  free(void *Ptr);
 void   Heap_Dump();
 
 // === GLOBALS ===
- int   glHeap;
+tSpinlock      glHeap;
 void   *gHeapStart;
 void   *gHeapEnd;
 

UCC git Repository :: git.ucc.asn.au