-BUILD_NUM = 18
+BUILD_NUM = 39
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
; 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
#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
// === 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);
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;
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
#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;
* 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 ===
// === 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;
{
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
/**
* \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 );
}
// 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);
// === 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;
// === 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;
#if USE_MP
tMPTable *mptable;
+ // Mark BSP as active
+ gaCPUs[0].State = 2;
+
// -- Initialise Multiprocessing
// Find MP Floating Table
// - EBDA/Last 1Kib (640KiB)
// 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);
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 {
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++) {
#endif
#if USE_MP
- gCurrentThread[0] = &gThreadZero;
+ gaCPUs[0].Current = &gThreadZero;
#else
gCurrentThread = &gThreadZero;
#endif
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
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
// Get current thread
#if USE_MP
- thread = gCurrentThread[CPU];
+ thread = gaCPUs[CPU].Current;
#else
curThread = gCurrentThread;
#endif
// Set current thread
#if USE_MP
- gCurrentThread[CPU] = thread;
+ gaCPUs[CPU].Current = thread;
#else
gCurrentThread = thread;
#endif
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
Uint32 CommandLine;
Uint32 ModuleCount;
Uint32 Modules;
+ Uint32 SymbolInfo[4]; // #32 UNUSED
+ Uint32 MMapLength;
+ Uint32 MMapAddr; // #40
} tMBoot_Info;
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
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:
$(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:
$(CLEAN_USRAPPS): clean-%:
@$(SUBMAKE) clean -C Usermode/Applications/$*_src
+# Install
$(INSTALL_MODULES): install-%:
@$(SUBMAKE) install -C Modules/$*
install-Kernel: