From d52a53f035af92941c0cafe5f81888fed16d2462 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 1 Jan 2010 17:37:26 +0800 Subject: [PATCH] More SMP Work, also changed the physical allocator to allocate downwards --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86/Makefile | 16 +++ Kernel/arch/x86/desctab.asm | 7 +- Kernel/arch/x86/include/arch.h | 14 +- Kernel/arch/x86/include/mm_phys.h | 2 +- Kernel/arch/x86/include/mp.h | 63 +++++++-- Kernel/arch/x86/include/proc.h | 9 ++ Kernel/arch/x86/mm_phys.c | 218 ++++++++++++++++++++++++------ Kernel/arch/x86/mm_virt.c | 11 +- Kernel/arch/x86/proc.c | 142 ++++++++++++++++--- Kernel/arch/x86/start.asm | 46 +++++++ Kernel/include/mboot.h | 10 ++ Makefile | 19 ++- 13 files changed, 467 insertions(+), 92 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 83042ca8..96e78f41 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 18 +BUILD_NUM = 39 diff --git a/Kernel/arch/x86/Makefile b/Kernel/arch/x86/Makefile index 051d126e..319c8f6f 100644 --- a/Kernel/arch/x86/Makefile +++ b/Kernel/arch/x86/Makefile @@ -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 diff --git a/Kernel/arch/x86/desctab.asm b/Kernel/arch/x86/desctab.asm index aad49c5f..bc37711b 100644 --- a/Kernel/arch/x86/desctab.asm +++ b/Kernel/arch/x86/desctab.asm @@ -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 diff --git a/Kernel/arch/x86/include/arch.h b/Kernel/arch/x86/include/arch.h index ccd1875f..18267576 100644 --- a/Kernel/arch/x86/include/arch.h +++ b/Kernel/arch/x86/include/arch.h @@ -26,19 +26,7 @@ #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 diff --git a/Kernel/arch/x86/include/mm_phys.h b/Kernel/arch/x86/include/mm_phys.h index 2d35587d..51a9cd30 100644 --- a/Kernel/arch/x86/include/mm_phys.h +++ b/Kernel/arch/x86/include/mm_phys.h @@ -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); diff --git a/Kernel/arch/x86/include/mp.h b/Kernel/arch/x86/include/mp.h index c2e910d7..45d24727 100644 --- a/Kernel/arch/x86/include/mp.h +++ b/Kernel/arch/x86/include/mp.h @@ -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 diff --git a/Kernel/arch/x86/include/proc.h b/Kernel/arch/x86/include/proc.h index 5a99c9c5..0a1d7548 100644 --- a/Kernel/arch/x86/include/proc.h +++ b/Kernel/arch/x86/include/proc.h @@ -11,6 +11,15 @@ #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; diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index 59662e9b..bd8d60e4 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -2,11 +2,13 @@ * Acess2 * - Physical memory manager */ -#define DEBUG 1 +#define DEBUG 0 #include #include #include +#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= 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<>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= 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 ); diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 4f272e75..5afc86f9 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -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); diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 018b5632..98ba7e0c 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -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;posAddr = 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 diff --git a/Kernel/arch/x86/start.asm b/Kernel/arch/x86/start.asm index 41351600..4dd76036 100644 --- a/Kernel/arch/x86/start.asm +++ b/Kernel/arch/x86/start.asm @@ -52,6 +52,52 @@ start: hlt jmp .hlt +; +; Multiprocessing AP Startup Code (Must be within 0x10FFF0) +; +%if USE_MP +[extern gGDTptr] +[extern gpMP_LocalAPIC] +[extern gaAPIC_to_CPU] +[extern gaCPUs] +[global APStartup] + +[bits 16] +APStartup: + xchg bx, bx ; MAGIC BREAK! + mov ax, 0xFFFF + mov ds, ax + lgdt [DWORD ds:gGDTptr-0xFFFF0] + mov eax, cr0 + or al, 1 + mov cr0, eax + jmp 08h:DWORD .ProtectedMode +[bits 32] +.ProtectedMode: + ; Start Paging + mov eax, gaInitPageDir - KERNEL_BASE + mov cr3, eax + mov eax, cr0 + or eax, 0x80010000 ; PG and WP + mov cr0, eax + ; Jump to higher half + lea eax, [.higherHalf] + jmp eax +.higherHalf: + mov eax, [gpMP_LocalAPIC] + mov DWORD [eax], 0 + xor ecx, ecx + mov cl, BYTE [eax+0x10] + ; CL is now local APIC ID + mov cl, BYTE [gaAPIC_to_CPU+ecx] + ; CL is now the CPU ID + mov BYTE [gaCPUs+ecx*8+1], 1 + ; CPU is now marked as initialised +.hlt: + hlt + jmp .hlt +%endif + [global GetEIP] GetEIP: mov eax, [esp] diff --git a/Kernel/include/mboot.h b/Kernel/include/mboot.h index 764120f6..ff59d544 100644 --- a/Kernel/include/mboot.h +++ b/Kernel/include/mboot.h @@ -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 diff --git a/Makefile b/Makefile index 9a861fde..178ebf79 100644 --- 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: -- 2.20.1