More MP work (now APs start and use the LAPIC timer)
[tpg/acess2.git] / Kernel / arch / x86 / proc.c
index c9035e1..0708540 100644 (file)
@@ -17,6 +17,7 @@
 // === CONSTANTS ===
 #define        SWITCH_MAGIC    0xFFFACE55      // There is no code in this area
 // Base is 1193182
+#define TIMER_BASE     1193182
 #define TIMER_DIVISOR  11931   //~100Hz
 
 // === TYPES ===
@@ -73,9 +74,11 @@ void Proc_Scheduler(int CPU);
 #if USE_MP
 volatile int   giNumInitingCPUs = 0;
 tMPInfo        *gMPFloatPtr = NULL;
+volatile Uint32        giMP_TimerCount;        // Start Count for Local APIC Timer
 tAPIC  *gpMP_LocalAPIC = NULL;
 Uint8  gaAPIC_to_CPU[256] = {0};
 tCPU   gaCPUs[MAX_CPUS];
+tTSS   gaTSSs[MAX_CPUS];       // TSS Array
  int   giProc_BootProcessorID = 0;
 #else
 tThread        *gCurrentThread = NULL;
@@ -83,16 +86,16 @@ tThread     *gCurrentThread = NULL;
 #if USE_PAE
 Uint32 *gPML4s[4] = NULL;
 #endif
-tTSS   *gTSSs = NULL;
+tTSS   *gTSSs = NULL;  // Pointer to TSS array
 tTSS   gTSS0 = {0};
 // --- Error Recovery ---
-char   gaDoubleFaultStack[1024];
+char   gaDoubleFaultStack[1024] __attribute__ ((section(".padata")));
 tTSS   gDoubleFault_TSS = {
-       .ESP0 = (Uint)&gaDoubleFaultStack[1023],
+       .ESP0 = (Uint)&gaDoubleFaultStack[1024],
        .SS0 = 0x10,
        .CR3 = (Uint)gaInitPageDir - KERNEL_BASE,
        .EIP = (Uint)Isr8,
-       .ESP = (Uint)&gaDoubleFaultStack[1023],
+       .ESP = (Uint)&gaDoubleFaultStack[1024],
        .CS = 0x08,     .SS = 0x10,
        .DS = 0x10,     .ES = 0x10,
        .FS = 0x10,     .GS = 0x10,
@@ -226,6 +229,8 @@ void ArchThreads_Init(void)
                                }
                                
                                break;
+                       
+                       #if DUMP_MP_TABLES
                        case 1: // Bus
                                entSize = 8;
                                Log("%i: Bus", i);
@@ -263,6 +268,7 @@ void ArchThreads_Init(void)
                        default:
                                Log("%i: Unknown (%i)", i, ents->Type);
                                break;
+                       #endif
                        }
                        ents = (void*)( (Uint)ents + entSize );
                }
@@ -271,6 +277,7 @@ void ArchThreads_Init(void)
                        Warning("Too many CPUs detected (%i), only using %i of them", giNumCPUs, MAX_CPUS);
                        giNumCPUs = MAX_CPUS;
                }
+               gTSSs = gaTSSs;
        }
        else {
                Log("No MP Table was found, assuming uniprocessor\n");
@@ -283,6 +290,7 @@ void ArchThreads_Init(void)
        MM_FinishVirtualInit();
        #endif
        
+       #if 0
        // Initialise Double Fault TSS
        gGDT[5].BaseLow = (Uint)&gDoubleFault_TSS & 0xFFFF;
        gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16;
@@ -293,8 +301,34 @@ void ArchThreads_Init(void)
        gIDT[8].CS = 5<<3;
        gIDT[8].Flags = 0x8500;
        gIDT[8].OffsetHi = 0;
+       #endif
+       
+       // Set timer frequency
+       outb(0x43, 0x34);       // Set Channel 0, Low/High, Rate Generator
+       outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
+       outb(0x40, (TIMER_DIVISOR>>8)&0xFF);    // High Byte
        
        #if USE_MP
+       // Get the count setting for APIC timer
+       Log("Determining APIC Count");
+       __asm__ __volatile__ ("sti");
+       while( giMP_TimerCount == 0 )   __asm__ __volatile__ ("hlt");
+       __asm__ __volatile__ ("cli");
+       Log("APIC Count %i", giMP_TimerCount);
+       {
+               Uint64  freq = giMP_TimerCount;
+               freq /= TIMER_DIVISOR;
+               freq *= TIMER_BASE;
+               if( (freq /= 1000) < 2*1000)
+                       Log("Bus Frequency %i KHz", freq);
+               else if( (freq /= 1000) < 2*1000)
+                       Log("Bus Frequency %i MHz", freq);
+               else if( (freq /= 1000) < 2*1000)
+                       Log("Bus Frequency %i GHz", freq);
+               else
+                       Log("Bus Frequency %i THz", freq);
+       }
+       
        // Initialise Normal TSS(s)
        for(pos=0;pos<giNumCPUs;pos++)
        {
@@ -314,13 +348,15 @@ void ArchThreads_Init(void)
        {
                gaCPUs[pos].Current = NULL;
                if( pos != giProc_BootProcessorID ) {
-                       Log("Starting AP %i, (APIC %i)\n", pos, gaCPUs[pos].APICID);
                        MP_StartAP( pos );
                }
        }
        
        Log("Waiting for APs to come up\n");
+       //__asm__ __volatile__ ("xchg %bx, %bx");
+       __asm__ __volatile__ ("sti");
        while( giNumInitingCPUs )       __asm__ __volatile__ ("hlt");
+       __asm__ __volatile__ ("cli");
        MM_FinishVirtualInit();
        //Panic("Uh oh... MP Table Parsing is unimplemented\n");
        #endif
@@ -342,11 +378,6 @@ void ArchThreads_Init(void)
        gThreadZero.MemState.CR3 = (Uint)gaInitPageDir - KERNEL_BASE;
        #endif
        
-       // Set timer frequency
-       outb(0x43, 0x34);       // Set Channel 0, Low/High, Rate Generator
-       outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
-       outb(0x40, (TIMER_DIVISOR>>8)&0xFF);    // High Byte
-       
        // Create Per-Process Data Block
        MM_Allocate(MM_PPD_CFG);
        
@@ -368,6 +399,8 @@ void MP_StartAP(int CPU)
        // Delay
        inb(0x80); inb(0x80); inb(0x80); inb(0x80);
        
+       // TODO: Use a better address, preferably registered with the MM
+       // - MM_AllocDMA mabye?
        // Create a far jump
        *(Uint8*)(KERNEL_BASE|0x11000) = 0xEA;  // Far JMP
        *(Uint16*)(KERNEL_BASE|0x11001) = (Uint)&APStartup - (KERNEL_BASE|0xFFFF0);     // IP
@@ -387,18 +420,16 @@ void MP_StartAP(int CPU)
  */
 void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode)
 {
-       Uint32  addr = (Uint)gpMP_LocalAPIC + 0x300;
        Uint32  val;
        
        // Hi
        val = (Uint)APICID << 24;
-       Log("*%p = 0x%08x", addr+0x10, val);
-       *(Uint32*)(addr+0x10) = val;
-       
+       Log("*%p = 0x%08x", &gpMP_LocalAPIC->ICR[1], val);
+       gpMP_LocalAPIC->ICR[1].Val = val;
        // Low (and send)
        val = ((DeliveryMode & 7) << 8) | (Vector & 0xFF);
-       Log("*%p = 0x%08x", addr, val);
-       *(Uint32*)addr = val;
+       Log("*%p = 0x%08x", &gpMP_LocalAPIC->ICR[0], val);
+       gpMP_LocalAPIC->ICR[0].Val = val;
 }
 #endif
 
@@ -825,6 +856,8 @@ void Proc_Scheduler(int CPU)
        gCurrentThread = thread;
        #endif
        
+       //Log("CPU = %i", CPU);
+       
        // Update Kernel Stack pointer
        gTSSs[CPU].ESP0 = thread->KernelStack-4;
        

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