More SMP Work, also changed the physical allocator to allocate downwards
authorJohn Hodge <tpg@prelude.(none)>
Fri, 1 Jan 2010 09:37:26 +0000 (17:37 +0800)
committerJohn Hodge <tpg@prelude.(none)>
Fri, 1 Jan 2010 09:37:26 +0000 (17:37 +0800)
13 files changed:
Kernel/Makefile.BuildNum
Kernel/arch/x86/Makefile
Kernel/arch/x86/desctab.asm
Kernel/arch/x86/include/arch.h
Kernel/arch/x86/include/mm_phys.h
Kernel/arch/x86/include/mp.h
Kernel/arch/x86/include/proc.h
Kernel/arch/x86/mm_phys.c
Kernel/arch/x86/mm_virt.c
Kernel/arch/x86/proc.c
Kernel/arch/x86/start.asm
Kernel/include/mboot.h
Makefile

index 83042ca..96e78f4 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 18
+BUILD_NUM = 39
index 051d126..319c8f6 100644 (file)
@@ -13,6 +13,22 @@ CPPFLAGS     =
 CFLAGS         =
 ASFLAGS                = -f elf
 
+ifeq ($(ARCH),i386)
+       ASFLAGS += -D USE_MP=0 -D USE_PAE=0
+       CPPFLAGS += -DUSE_MP=0 -DUSE_PAE=0
+else
+       ifeq ($(ARCH),i486)
+               ASFLAGS += -D USE_MP=1 -D USE_PAE=0
+               CPPFLAGS += -DUSE_MP=1 -DUSE_PAE=0
+       else
+               ifeq ($(ARCH),i586)
+                       ASFLAGS += -D USE_MP=1 -D USE_PAE=1
+                       CPPFLAGS += -DUSE_MP=1 -DUSE_PAE=1
+               endif
+       endif
+endif
+       
+
 A_OBJ  = start.ao main.o lib.o desctab.ao errors.o irq.o
 A_OBJ += mm_phys.o mm_virt.o
 A_OBJ += proc.o time.o
index aad49c5..bc37711 100644 (file)
@@ -3,16 +3,17 @@
 ; desctab.asm
 [BITS 32]
 
-%if ARCH == "i386"
-MAX_CPUS       equ     1
-%else
+%if USE_MP
 MAX_CPUS       equ     8
+%else
+MAX_CPUS       equ     1
 %endif
 GDT_SIZE       equ     (1+2*2+1+MAX_CPUS)*8
 
 [section .data]
 ; GDT
 [global gGDT]
+[global gGDTptr]
 gGDT:
        ; PL0 - Kernel
        ; PL3 - User
index ccd1875..1826757 100644 (file)
 #define BITS   32
 
 // - Processor/Machine Specific Features
-#if ARCH == i386
-// Uses no advanced features
-# define       USE_MP  0
-# define       USE_PAE 0
-#elif ARCH == i486
-// MP Only
-# define       USE_MP  1
-# define       USE_PAE 0
-#elif ARCH == i586
-// All Enabled
-# define       USE_MP  1
-# define       USE_PAE 1
-#else
+#if ARCH != i386 && ARCH != i486 && ARCH != i586
 # error "Unknown architecture '" #ARCH "'"
 #endif
 
index 2d35587..51a9cd3 100644 (file)
@@ -7,7 +7,7 @@
 
 // === FUNCTIONS ===
 extern tPAddr  MM_AllocPhys();
-extern tPAddr  MM_AllocPhysRange(int Pages);
+extern tPAddr  MM_AllocPhysRange(int Pages, int MaxBits);
 extern void    MM_RefPhys(tPAddr Addr);
 extern void    MM_DerefPhys(tPAddr Addr);
 extern int     MM_GetRefCount(tPAddr Addr);
index c2e910d..45d2472 100644 (file)
@@ -15,6 +15,49 @@ typedef struct sMPInfo {
        Uint8   Features[5];    // 2-4 are unused
 } tMPInfo;
 
+typedef union uMPTable_Ent {
+       Uint8   Type;
+       struct {
+               Uint8   Type;
+               Uint8   APICID;
+               Uint8   APICVer;
+               Uint8   CPUFlags;       // bit 0: Enabled, bit 1: Boot Processor
+               Uint32  CPUSignature;   // Stepping, Model, Family
+               Uint32  FeatureFlags;
+               Uint32  Reserved[2];
+       } __attribute__((packed))       Proc;   // 0x00
+       struct {
+               Uint8   Type;
+               Uint8   ID;
+               char    TypeString[6];
+       } __attribute__((packed))       Bus;    // 0x01
+       struct {
+               Uint8   Type;
+               Uint8   ID;
+               Uint8   Version;
+               Uint8   Flags;  // bit 0: Enabled
+               Uint32  Addr;
+       } __attribute__((packed))       IOAPIC; // 0x02
+       struct {
+               Uint8   Type;
+               Uint8   IntType;
+               Uint16  Flags;  // 0,1: Polarity, 2,3: Trigger Mode
+               Uint8   SourceBusID;
+               Uint8   SourceBusIRQ;
+               Uint8   DestAPICID;
+               Uint8   DestAPICIRQ;
+       } __attribute__((packed))       IOInt;
+       struct {
+               Uint8   Type;
+               Uint8   IntType;
+               Uint16  Flags;  // 0,1: Polarity, 2,3: Trigger Mode
+               Uint8   SourceBusID;
+               Uint8   SourceBusIRQ;
+               Uint8   DestLocalAPICID;
+               Uint8   DestLocalAPICIRQ;
+       } __attribute__((packed))       LocalInt;
+} __attribute__((packed)) tMPTable_Ent;
+
 typedef struct sMPTable {
        Uint32  Sig;
        Uint16  BaseTableLength;
@@ -32,16 +75,18 @@ typedef struct sMPTable {
        Uint16  ExtendedTableLen;
        Uint8   ExtendedTableChecksum;
        Uint8   Reserved;
+       
+       tMPTable_Ent    Entries[];
 } tMPTable;
 
-typedef struct sMPTable_Proc {
-       Uint8   Type;   // 0x00
-       Uint8   APICID;
-       Uint8   APICVer;
-       Uint8   CPUFlags;       // bit 0: Disabled, bit 1: Boot Processor
-       Uint32  CPUSignature;   // Stepping, Model, Family
-       Uint32  FeatureFlags;
-       Uint32  Reserved[2];
-} tMPTable_Proc;
+typedef volatile struct {
+       Uint8   Addr;
+       Uint8   Resvd[3];
+       Uint32  Resvd2[3];
+       union {
+               Uint8   Byte;
+               Uint32  DWord;
+       }       Value;
+}      tIOAPIC;
 
 #endif
index 5a99c9c..0a1d754 100644 (file)
 #define GETMSG_IGNORE  ((void*)-1)
 
 // === TYPES ===
+#if USE_MP
+typedef struct sCPU
+{
+       Uint8   APICID;
+       Uint8   State;  // 0: Unavaliable, 1: Idle, 2: Active
+       Uint16  Resvd;
+       tThread *Current;
+}      tCPU;
+#endif
 
 typedef struct sTSS {
        Uint32  Link;
index 59662e9..bd8d60e 100644 (file)
@@ -2,11 +2,13 @@
  * Acess2
  * - Physical memory manager
  */
-#define DEBUG  1
+#define DEBUG  0
 #include <acess.h>
 #include <mboot.h>
 #include <mm_virt.h>
 
+#define USE_STACK      1
+
 #define        REFERENCE_BASE  0xE0400000
 
 // === IMPORTS ===
@@ -14,13 +16,15 @@ extern void gKernelEnd;
 
 // === PROTOTYPES ===
 tPAddr MM_AllocPhys();
-tPAddr MM_AllocPhysRange(int Pages);
+tPAddr MM_AllocPhysRange(int Pages, int MaxBits);
 void   MM_RefPhys(tPAddr Addr);
 void   MM_DerefPhys(tPAddr Addr);
 
 // === GLOBALS ===
- int   giPhysAlloc = 0;
-Uint   giPageCount = 0;
+Uint64 giPhysAlloc = 0;        // Number of allocated pages
+Uint64 giPageCount = 0;        // Total number of pages
+Uint64 giLastPossibleFree = 0; // Last possible free page (before all pages are used)
+
 Uint32 gaSuperBitmap[1024];    // Blocks of 1024 Pages
 Uint32 gaPageBitmap[1024*1024/32];     // Individual pages
 Uint32 *gaPageReferences;
@@ -30,26 +34,57 @@ void MM_Install(tMBoot_Info *MBoot)
 {
        Uint    kernelPages, num;
        Uint    i;
+       Uint64  maxAddr = 0;
        tMBoot_Module   *mods;
+       tMBoot_MMapEnt  *ent;
+       
+       // --- Find largest address
+       MBoot->MMapAddr |= KERNEL_BASE;
+       ent = (void *)( MBoot->MMapAddr );
+       while( (Uint)ent < MBoot->MMapAddr + MBoot->MMapLength )
+       {
+               // Adjust for size
+               ent->Size += 4;
+               
+               // 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 );
+       }
+       
+       if(maxAddr == 0) {      
+               giPageCount = (MBoot->HighMem >> 2) + 256;      // HighMem is a kByte value
+       }
+       else {
+               giPageCount = maxAddr >> 12;
+       }
+       giLastPossibleFree = giPageCount - 1;
        
-       // Initialise globals
-       giPageCount = (MBoot->HighMem >> 2) + 256;      // HighMem is a kByte value
-       //LOG("giPageCount = %i", giPageCount);
+       memsetd(gaPageBitmap, 0xFFFFFFFF, giPageCount/32);
+       
+       // Set up allocateable space
+       ent = (void *)( MBoot->MMapAddr );
+       while( (Uint)ent < MBoot->MMapAddr + MBoot->MMapLength )
+       {               
+               memsetd( &gaPageBitmap[ent->Base/(4096*32)], 0, ent->Length/(4096*32) );
+               ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size );
+       }
        
        // Get used page count
-       kernelPages = (Uint)&gKernelEnd - KERNEL_BASE;
+       kernelPages = (Uint)&gKernelEnd - KERNEL_BASE - 0x100000;
        kernelPages += 0xFFF;   // Page Align
        kernelPages >>= 12;
        
        // Fill page bitmap
        num = kernelPages/32;
-       memsetd(gaPageBitmap, -1, num);
-       gaPageBitmap[ num ] = (1 << (kernelPages & 31)) - 1;
+       memsetd( &gaPageBitmap[0x100000/(4096*32)], -1, num );
+       gaPageBitmap[ 0x100000/(4096*32) + num ] = (1 << (kernelPages & 31)) - 1;
        
        // Fill Superpage bitmap
        num = kernelPages/(32*32);
-       memsetd(gaSuperBitmap, -1, num);
-       gaSuperBitmap[ num ] = (1 << ((kernelPages / 32) & 31)) - 1;
+       memsetd( &gaSuperBitmap[0x100000/(4096*32*32)], -1, num );
+       gaSuperBitmap[ 0x100000/(4096*32*32) + num ] = (1 << ((kernelPages / 32) & 31)) - 1;
        
        // Mark Multiboot's pages as taken
        // - Structure
@@ -85,76 +120,183 @@ void MM_Install(tMBoot_Info *MBoot)
 
 /**
  * \fn tPAddr MM_AllocPhys()
- * \brief Allocates a physical page
+ * \brief Allocates a physical page from the general pool
  */
 tPAddr MM_AllocPhys()
 {
-        int    num = giPageCount / 32 / 32;
-        int    a, b, c;
+       // int  a, b, c;
+        int    indx;
        tPAddr  ret;
        
+       ENTER("");
+       
        LOCK( &giPhysAlloc );
        
        // Find free page
-       for(a=0;gaSuperBitmap[a]==-1&&a<num;a++);
-       if(a == num) {
+       // Scan downwards
+       #if 1
+       LOG("giLastPossibleFree = %i", giLastPossibleFree);
+       for( indx = giLastPossibleFree; indx >= 0; )
+       {
+               if( gaSuperBitmap[indx>>10] == -1 ) {
+                       indx -= 1024;
+                       continue;
+               }
+               if( gaPageBitmap[indx>>5] == -1 ) {
+                       indx -= 32;
+                       continue;
+               }
+               
+               if( gaPageBitmap[indx>>5] & (1 << (indx&31)) ) {
+                       indx --;
+                       continue;
+               }
+               break;
+       }
+       LOG("indx = %i", indx);
+       #else
+       c = giLastPossibleFree % 32;
+       b = (giLastPossibleFree / 32) % 32;
+       a = giLastPossibleFree / 1024;
+       
+       LOG("a=%i,b=%i,c=%i", a, b, c);
+       for( ; gaSuperBitmap[a] == -1 && a >= 0; a-- );
+       if(a < 0) {
                RELEASE( &giPhysAlloc );
                Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
+               LEAVE('i', 0);
                return 0;
        }
-       for(b=0;gaSuperBitmap[a]&(1<<b);b++);
-       for(c=0;gaPageBitmap[a*32+b]&(1<<c);c++);
+       for( ; gaSuperBitmap[a] & (1<<b); b-- );
+       for( ; gaPageBitmap[a*32+b] & (1<<c); c-- );
+       LOG("a=%i,b=%i,c=%i", a, b, c);
+       indx = (a << 10) | (b << 5) | c;
+       #endif
        
        // Mark page used
        if(gaPageReferences)
-               gaPageReferences[a*32*32+b*32+c] = 1;
-       gaPageBitmap[ a*32+b ] |= 1 << c;
+               gaPageReferences[ indx ] = 1;
+       gaPageBitmap[ indx>>5 ] |= 1 << (indx&31);
+       
        
        // Get address
-       ret = (a << 22) + (b << 17) + (c << 12);
+       ret = indx << 12;
+       giLastPossibleFree = indx;
        
        // Mark used block
-       if(gaPageBitmap[ a*32+b ] == -1)        gaSuperBitmap[a] |= 1 << b;
+       if(gaPageBitmap[ indx>>5 ] == -1)
+               gaSuperBitmap[indx>>10] |= 1 << ((indx>>5)&31);
 
        // Release Spinlock
        RELEASE( &giPhysAlloc );
        
+       LEAVE('X', ret);
+       //Log("MM_AllocPhys: RETURN 0x%x", ret);
        return ret;
 }
 
 /**
- * \fn tPAddr MM_AllocPhysRange(int Pages)
+ * \fn tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
  * \brief Allocate a range of physical pages
  * \param Pages        Number of pages to allocate
+ * \param MaxBits      Maximum number of address bits to use
  */
-tPAddr MM_AllocPhysRange(int Pages)
+tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
 {
-        int    num = giPageCount / 32 / 32;
-        int    a, b, c;
+        int    a, b;
+        int    i, idx, sidx;
        tPAddr  ret;
        
+       // Sanity Checks
+       if(MaxBits < 0) return 0;
+       if(MaxBits > PHYS_BITS) MaxBits = PHYS_BITS;
+       
+       // Lock
        LOCK( &giPhysAlloc );
        
+       // Set up search state
+       if( giLastPossibleFree > ((tPAddr)1 << (MaxBits-12)) ) {
+               sidx = (tPAddr)1 << (MaxBits-12);
+       }
+       else {
+               sidx = giLastPossibleFree;
+       }
+       idx = sidx / 32;
+       sidx %= 32;
+       b = idx % 32;
+       a = idx / 32;
+       
        // Find free page
-       for(a=0;gaSuperBitmap[a]==-1&&a<num;a++);
-       if(a == num) {
+       for( ; gaSuperBitmap[a] == -1 && a --; );
+       if(a < 0) {
                RELEASE( &giPhysAlloc );
-               Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
+               Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
                return 0;
        }
-       for(b=0;gaSuperBitmap[a]&(1<<b);b++);
-       for(c=0;gaPageBitmap[a*32+b]&(1<<c);c++);
+       for( ; gaSuperBitmap[a] & (1 << b); b-- );
+       idx = a * 32 + b;
+       for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- );
        
-       // Mark page used
-       if(gaPageReferences)
-               gaPageReferences[a*32*32+b*32+c] = 1;
-       gaPageBitmap[ a*32+b ] |= 1 << c;
+       // Check if the gap is large enough
+       while( idx >= 0 )
+       {
+               // Find a free page
+               for( ; ; )
+               {
+                       // Bulk Skip
+                       if( gaPageBitmap[idx] == -1 ) {
+                               idx --;
+                               sidx = 31;
+                               continue;
+                       }
+                       
+                       if( gaPageBitmap[idx] & (1 << sidx) ) {
+                               sidx --;
+                               if(sidx < 0) {  sidx = 31;      idx --; }
+                               if(idx < 0)     break;
+                               continue;
+                       }
+                       break;
+               }
+               if( idx < 0 )   break;
+               
+               // Check if it is a free range
+               for( i = 0; i < Pages; i++ )
+               {
+                       // Used page? break
+                       if( gaPageBitmap[idx] & (1 << sidx) )
+                               break;
+                       
+                       sidx --;
+                       if(sidx < 0) {  sidx = 31;      idx --; }
+                       if(idx < 0)     break;
+               }
+               
+               if( i == Pages )
+                       break;
+       }
+       
+       // Check if an address was found
+       if( idx < 0 ) {
+               RELEASE( &giPhysAlloc );
+               Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
+       }
+       
+       // Mark pages used
+       for( i = 0; i < Pages; i++ )
+       {
+               if(gaPageReferences)
+                       gaPageReferences[idx*32+sidx] = 1;
+               gaPageBitmap[ idx ] |= 1 << sidx;
+               sidx ++;
+               if(sidx == 32) {        sidx = 0;       idx ++; }
+       }
        
        // Get address
-       ret = (a << 22) + (b << 17) + (c << 12);
+       ret = (idx << 17) | (sidx << 12);
        
        // Mark used block
-       if(gaPageBitmap[ a*32+b ] == -1)        gaSuperBitmap[a] |= 1 << b;
+       if(gaPageBitmap[ idx ] == -1)   gaSuperBitmap[idx/32] |= 1 << (idx%32);
 
        // Release Spinlock
        RELEASE( &giPhysAlloc );
index 4f272e7..5afc86f 100644 (file)
@@ -958,21 +958,12 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        }
        
        // Slow Allocate
-       phys = MM_AllocPhysRange(Pages);
+       phys = MM_AllocPhysRange(Pages, MaxBits);
        // - Was it allocated?
        if(phys == 0) {
                LEAVE('i', 0);
                return 0;
        }
-       // - Check if the memory is OK
-       if(phys + (Pages-1)*0x1000 > maxCheck)
-       {
-               // Deallocate and return 0
-               for(;Pages--;phys+=0x1000)
-                       MM_DerefPhys(phys);
-               LEAVE('i', 0);
-               return 0;
-       }
        
        // Allocated successfully, now map
        ret = MM_MapHWPage(phys, Pages);
index 018b563..98ba7e0 100644 (file)
@@ -19,6 +19,7 @@
 
 // === IMPORTS ===
 extern tGDT    gGDT[];
+extern void APStartup();       // 16-bit AP startup code
 extern Uint    GetEIP();       // start.asm
 extern Uint32  gaInitPageDir[1024];    // start.asm
 extern void    Kernel_Stack_Top;
@@ -38,21 +39,25 @@ extern void Isr7();
 
 // === PROTOTYPES ===
 void   ArchThreads_Init();
+#if USE_MP
+void   MP_StartAP(int CPU);
+void   MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode);
+#endif
+void   Proc_Start();
 tThread        *Proc_GetCurThread();
 void   Proc_ChangeStack();
  int   Proc_Clone(Uint *Err, Uint Flags);
 void   Proc_Scheduler();
 
 // === GLOBALS ===
-// --- Current State ---
-#if USE_MP
-tThread        *gCurrentThread[MAX_CPUS] = {NULL};
-#else
-tThread        *gCurrentThread = NULL;
-#endif
 // --- Multiprocessing ---
 #if USE_MP
 tMPInfo        *gMPFloatPtr = NULL;
+tIOAPIC        *gpMP_LocalAPIC = NULL;
+Uint8  gaAPIC_to_CPU[256] = {0};
+tCPU   gaCPUs[MAX_CPUS];
+#else
+tThread        *gCurrentThread = NULL;
 #endif
 #if USE_PAE
 Uint32 *gPML4s[4] = NULL;
@@ -79,6 +84,9 @@ void ArchThreads_Init()
        #if USE_MP
        tMPTable        *mptable;
        
+       // Mark BSP as active
+       gaCPUs[0].State = 2;
+       
        // -- Initialise Multiprocessing
        // Find MP Floating Table
        // - EBDA/Last 1Kib (640KiB)
@@ -116,6 +124,8 @@ void ArchThreads_Init()
        // If the MP Table Exists, parse it
        if(gMPFloatPtr)
        {
+                int    i;
+               tMPTable_Ent    *ents;
                Log("gMPFloatPtr = %p", gMPFloatPtr);
                Log("*gMPFloatPtr = {");
                Log("\t.Sig = 0x%08x", gMPFloatPtr->Sig);
@@ -139,8 +149,94 @@ void ArchThreads_Init()
                Log("\t.Checksum = 0x%02x", mptable->Checksum);
                Log("\t.OEMID = '%8c'", mptable->OemID);
                Log("\t.ProductID = '%8c'", mptable->ProductID);
+               Log("\t.OEMTablePtr = %p'", mptable->OEMTablePtr);
+               Log("\t.OEMTableSize = 0x%04x", mptable->OEMTableSize);
+               Log("\t.EntryCount = 0x%04x", mptable->EntryCount);
+               Log("\t.LocalAPICMemMap = 0x%08x", mptable->LocalAPICMemMap);
+               Log("\t.ExtendedTableLen = 0x%04x", mptable->ExtendedTableLen);
+               Log("\t.ExtendedTableChecksum = 0x%02x", mptable->ExtendedTableChecksum);
                Log("}");
                
+               gpMP_LocalAPIC = (void*)MM_MapHWPage(mptable->LocalAPICMemMap, 1);
+               
+               ents = mptable->Entries;
+               giNumCPUs = 0;
+               
+               for( i = 0; i < mptable->EntryCount; i ++ )
+               {
+                        int    entSize = 0;
+                       switch( ents->Type )
+                       {
+                       case 0: // Processor
+                               entSize = 20;
+                               Log("%i: Processor", i);
+                               Log("\t.APICID = %i", ents->Proc.APICID);
+                               Log("\t.APICVer = 0x%02x", ents->Proc.APICVer);
+                               Log("\t.CPUFlags = 0x%02x", ents->Proc.CPUFlags);
+                               Log("\t.CPUSignature = 0x%08x", ents->Proc.CPUSignature);
+                               Log("\t.FeatureFlags = 0x%08x", ents->Proc.FeatureFlags);
+                               
+                               // Check if there is too many processors
+                               if(giNumCPUs >= MAX_CPUS) {
+                                       giNumCPUs ++;   // If `giNumCPUs` > MAX_CPUS later, it will be clipped
+                                       break;
+                               }
+                               
+                               // Initialise CPU Info
+                               gaAPIC_to_CPU[ents->Proc.APICID] = giNumCPUs;
+                               gaCPUs[giNumCPUs].APICID = ents->Proc.APICID;
+                               gaCPUs[giNumCPUs].State = 0;
+                               giNumCPUs ++;
+                               
+                               // Send IPI
+                               MP_StartAP( giNumCPUs-1 );
+                               
+                               break;
+                       case 1: // Bus
+                               entSize = 8;
+                               Log("%i: Bus", i);
+                               Log("\t.ID = %i", ents->Bus.ID);
+                               Log("\t.TypeString = '%6c'", ents->Bus.TypeString);
+                               break;
+                       case 2: // I/O APIC
+                               entSize = 8;
+                               Log("%i: I/O APIC", i);
+                               Log("\t.ID = %i", ents->IOAPIC.ID);
+                               Log("\t.Version = 0x%02x", ents->IOAPIC.Version);
+                               Log("\t.Flags = 0x%02x", ents->IOAPIC.Flags);
+                               Log("\t.Addr = 0x%08x", ents->IOAPIC.Addr);
+                               break;
+                       case 3: // I/O Interrupt Assignment
+                               entSize = 8;
+                               Log("%i: I/O Interrupt Assignment", i);
+                               Log("\t.IntType = %i", ents->IOInt.IntType);
+                               Log("\t.Flags = 0x%04x", ents->IOInt.Flags);
+                               Log("\t.SourceBusID = 0x%02x", ents->IOInt.SourceBusID);
+                               Log("\t.SourceBusIRQ = 0x%02x", ents->IOInt.SourceBusIRQ);
+                               Log("\t.DestAPICID = 0x%02x", ents->IOInt.DestAPICID);
+                               Log("\t.DestAPICIRQ = 0x%02x", ents->IOInt.DestAPICIRQ);
+                               break;
+                       case 4: // Local Interrupt Assignment
+                               entSize = 8;
+                               Log("%i: Local Interrupt Assignment", i);
+                               Log("\t.IntType = %i", ents->LocalInt.IntType);
+                               Log("\t.Flags = 0x%04x", ents->LocalInt.Flags);
+                               Log("\t.SourceBusID = 0x%02x", ents->LocalInt.SourceBusID);
+                               Log("\t.SourceBusIRQ = 0x%02x", ents->LocalInt.SourceBusIRQ);
+                               Log("\t.DestLocalAPICID = 0x%02x", ents->LocalInt.DestLocalAPICID);
+                               Log("\t.DestLocalAPICIRQ = 0x%02x", ents->LocalInt.DestLocalAPICIRQ);
+                               break;
+                       default:
+                               Log("%i: Unknown (%i)", i, ents->Type);
+                               break;
+                       }
+                       ents = (void*)( (Uint)ents + entSize );
+               }
+               
+               if( giNumCPUs > MAX_CPUS ) {
+                       Warning("Too many CPUs detected (%i), only using %i of them", giNumCPUs, MAX_CPUS);
+               }
+               
                Panic("Uh oh... MP Table Parsing is unimplemented\n");
        }
        else {
@@ -176,12 +272,6 @@ void ArchThreads_Init()
                gGDT[6+pos].BaseLow = ((Uint)(&gTSSs[pos])) & 0xFFFF;
                gGDT[6+pos].BaseMid = ((Uint)(&gTSSs[pos])) >> 16;
                gGDT[6+pos].BaseHi = ((Uint)(&gTSSs[pos])) >> 24;
-               /*
-               gGDT[6+pos].LimitLow = sizeof(tTSS);
-               gGDT[6+pos].LimitHi = 0;
-               gGDT[6+pos].Access = 0x89;      // Type
-               gGDT[6+pos].Flags = 0x4;
-               */
        #if USE_MP
        }
        for(pos=0;pos<giNumCPUs;pos++) {
@@ -192,7 +282,7 @@ void ArchThreads_Init()
        #endif
        
        #if USE_MP
-       gCurrentThread[0] = &gThreadZero;
+       gaCPUs[0].Current = &gThreadZero;
        #else
        gCurrentThread = &gThreadZero;
        #endif
@@ -217,6 +307,25 @@ void ArchThreads_Init()
        Proc_ChangeStack();
 }
 
+#if USE_MP
+void MP_StartAP(int CPU)
+{
+       Log("Starting AP %i (APIC %i)", CPU, gaCPUs[CPU].APICID);
+       // Set location of AP startup code and mark for a warm restart
+       *(Uint16*)(KERNEL_BASE|0x467) = (Uint)&APStartup - (KERNEL_BASE|0xFFFF0);
+       *(Uint16*)(KERNEL_BASE|0x469) = 0xFFFF;
+       outb(0x70, 0x0F);       outb(0x71, 0x0A);       // Warm Reset
+       MP_SendIPI(gaCPUs[CPU].APICID, 0, 5);
+}
+
+void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode)
+{
+       Uint32  addr = (Uint)gpMP_LocalAPIC + 0x20 + (APICID<<3);
+       
+       *(Uint32*)addr = ((DeliveryMode & 7) << 8) | (Vector & 0xFF);
+}
+#endif
+
 /**
  * \fn void Proc_Start()
  * \brief Start process scheduler
@@ -234,7 +343,8 @@ void Proc_Start()
 tThread *Proc_GetCurThread()
 {
        #if USE_MP
-       return NULL;
+       gpMP_LocalAPIC->Addr = 0;
+       return gaCPUs[ gaAPIC_to_CPU[gpMP_LocalAPIC->Value.Byte] ].Current;
        #else
        return gCurrentThread;
        #endif
@@ -567,7 +677,7 @@ void Proc_Scheduler(int CPU)
        
        // Get current thread
        #if USE_MP
-       thread = gCurrentThread[CPU];
+       thread = gaCPUs[CPU].Current;
        #else
        curThread = gCurrentThread;
        #endif
@@ -607,7 +717,7 @@ void Proc_Scheduler(int CPU)
        
        // Set current thread
        #if USE_MP
-       gCurrentThread[CPU] = thread;
+       gaCPUs[CPU].Current = thread;
        #else
        gCurrentThread = thread;
        #endif
index 4135160..4dd7603 100644 (file)
@@ -52,6 +52,52 @@ start:
        hlt\r
        jmp .hlt\r
 \r
+; \r
+; Multiprocessing AP Startup Code (Must be within 0x10FFF0)\r
+;\r
+%if USE_MP\r
+[extern gGDTptr]\r
+[extern gpMP_LocalAPIC]\r
+[extern gaAPIC_to_CPU]\r
+[extern gaCPUs]\r
+[global APStartup]\r
+\r
+[bits 16]\r
+APStartup:\r
+       xchg bx, bx     ; MAGIC BREAK!\r
+       mov ax, 0xFFFF\r
+       mov ds, ax\r
+       lgdt [DWORD ds:gGDTptr-0xFFFF0]\r
+       mov eax, cr0\r
+       or      al, 1\r
+       mov     cr0, eax\r
+       jmp 08h:DWORD .ProtectedMode\r
+[bits 32]\r
+.ProtectedMode:\r
+       ; Start Paging\r
+       mov eax, gaInitPageDir - KERNEL_BASE\r
+       mov cr3, eax\r
+       mov eax, cr0\r
+       or      eax, 0x80010000 ; PG and WP\r
+       mov cr0, eax\r
+       ; Jump to higher half\r
+       lea eax, [.higherHalf]\r
+       jmp eax\r
+.higherHalf:\r
+       mov eax, [gpMP_LocalAPIC]\r
+       mov DWORD [eax], 0\r
+       xor ecx, ecx\r
+       mov cl, BYTE [eax+0x10]\r
+       ; CL is now local APIC ID\r
+       mov cl, BYTE [gaAPIC_to_CPU+ecx]\r
+       ; CL is now the CPU ID\r
+       mov BYTE [gaCPUs+ecx*8+1], 1\r
+       ; CPU is now marked as initialised\r
+.hlt:\r
+       hlt\r
+       jmp .hlt\r
+%endif\r
+\r
 [global GetEIP]\r
 GetEIP:\r
        mov eax, [esp]\r
index 764120f..ff59d54 100644 (file)
@@ -14,6 +14,9 @@ typedef struct {
        Uint32  CommandLine;
        Uint32  ModuleCount;
        Uint32  Modules;
+       Uint32  SymbolInfo[4];  // #32 UNUSED
+       Uint32  MMapLength;
+       Uint32  MMapAddr;               // #40
 } tMBoot_Info;
 
 typedef struct {
@@ -23,4 +26,11 @@ typedef struct {
        Uint32  Resvd;
 } tMBoot_Module;
 
+typedef struct {
+       Uint32  Size;   // (May be at offset -4)
+       Uint64  Base;
+       Uint64  Length;
+       Uint32  Type;   //1:RAM,Else Reserved
+} __attribute__ ((packed)) tMBoot_MMapEnt;
+
 #endif
index 9a861fd..178ebf7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,17 +21,22 @@ CLEAN_USRAPPS = $(addprefix clean-,$(USRAPPS))
 INSTALL_MODULES = $(addprefix install-,$(MODULES))
 INSTALL_USRLIBS = $(addprefix install-,$(USRLIBS))
 INSTALL_USRAPPS = $(addprefix install-,$(USRAPPS))
+ALLINSTALL_MODULES = $(addprefix allinstall-,$(MODULES))
+ALLINSTALL_USRLIBS = $(addprefix allinstall-,$(USRLIBS))
+ALLINSTALL_USRAPPS = $(addprefix allinstall-,$(USRAPPS))
 
 .PHONY: all clean install \
        $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) \
+       $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS) \
        $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) \
        $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
 
 all:   $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS)
+all-install:   $(ALLINSTALL_MODULES) all-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS)
 clean: $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
 install:       $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
 
-
+# Compile Only
 $(ALL_MODULES): all-%:
        @echo === Module: $* && $(SUBMAKE) all -C Modules/$*
 all-Kernel:
@@ -41,6 +46,17 @@ $(ALL_USRLIBS): all-%:
 $(ALL_USRAPPS): all-%:
        @echo === User Application: $* && $(SUBMAKE) all -C Usermode/Applications/$*_src
 
+# Compile & Install
+$(ALLINSTALL_MODULES): allinstall-%:
+       @echo === Module: $* && $(SUBMAKE) all install -C Modules/$*
+allinstall-Kernel:
+       @echo === Kernel && $(SUBMAKE) all install -C Kernel
+$(ALLINSTALL_USRLIBS): allinstall-%:
+       @echo === User Library: $* && $(SUBMAKE) all install -C Usermode/Libraries/$*_src
+$(ALLINSTALL_USRAPPS): allinstall-%:
+       @echo === User Application: $* && $(SUBMAKE) all install -C Usermode/Applications/$*_src
+
+# Clean up compilation
 $(CLEAN_MODULES): clean-%:
        @$(SUBMAKE) clean -C Modules/$*
 clean-Kernel:
@@ -50,6 +66,7 @@ $(CLEAN_USRLIBS): clean-%:
 $(CLEAN_USRAPPS): clean-%:
        @$(SUBMAKE) clean -C Usermode/Applications/$*_src
 
+# Install
 $(INSTALL_MODULES): install-%:
        @$(SUBMAKE) install -C Modules/$*
 install-Kernel:

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