Sync to trunk head (r42241)
[reactos.git] / reactos / hal / halx86 / mp / apic.c
index f6efcb4..651500a 100644 (file)
 
 /* INCLUDE ***********************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/i386/ps.h>
-
 #include <hal.h>
-#include <halirq.h>
-#include <mps.h>
-#include <apic.h>
-
+#include <halfuncs.h> /* Not in PCH because only used for MP HAL */
+#include <rtlfuncs.h> /* Not in PCH because only used for MP HAL */
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* GLOBALS ***********************************************************************/
 
@@ -61,7 +56,8 @@ ULONG lastregw[MAX_CPU];
 ULONG lastvalw[MAX_CPU];
 
 #ifdef CONFIG_SMP
-typedef struct __attribute__((packed)) _COMMON_AREA_INFO
+#include <pshpack1.h>
+typedef struct _COMMON_AREA_INFO
 {
    ULONG Stack;                    /* Location of AP stack */
    ULONG PageDirectory;            /* Page directory for an AP */
@@ -69,6 +65,7 @@ typedef struct __attribute__((packed)) _COMMON_AREA_INFO
    ULONG PaeModeEnabled;    /* PAE mode is enabled */
    ULONG Debug[16];        /* For debugging */
 } COMMON_AREA_INFO, *PCOMMON_AREA_INFO;
+#include <poppack.h>
 #endif
 
 CHAR *APstart, *APend;
@@ -79,17 +76,17 @@ CHAR *APstart, *APend;
 #define HZ             (100)
 #define APIC_DIVISOR   (16)
 
-#define CMOS_READ(address) ({ \
+#define CMOS_READ(address) { \
    WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \
    READ_PORT_UCHAR((PUCHAR)0x71)); \
-})
+}
 
-#define CMOS_WRITE(address, value) ({ \
+#define CMOS_WRITE(address, value) { \
    WRITE_PORT_UCHAR((PUCHAR)0x70, address); \
    WRITE_PORT_UCHAR((PUCHAR)0x71, value); \
-})
+}
 
-extern PVOID IMPORTED MmSystemRangeStart;
+extern ULONG_PTR KernelBase;
 
 /* FUNCTIONS *********************************************************************/
 
@@ -187,7 +184,7 @@ VOID EnableApicMode(VOID)
 }
 
 /* Disable symetric I/O mode ie. go to PIC mode */
-inline VOID DisableSMPMode(VOID)
+__inline VOID DisableSMPMode(VOID)
 {
    /*
     * Put the board back into PIC mode (has an effect
@@ -226,72 +223,6 @@ VOID APICDisable(VOID)
   APICWrite(APIC_SIVR, tmp);
 }
 
-
-inline ULONG _APICRead(ULONG Offset)
-{
-   PULONG p;
-
-   p = (PULONG)((ULONG)APICBase + Offset);
-   return *p;
-}
-
-#if 0
-inline VOID APICWrite(ULONG Offset,
-                     ULONG Value)
-{
-   PULONG p;
-
-   p = (PULONG)((ULONG)APICBase + Offset);
-
-   *p = Value;
-}
-#else
-inline VOID APICWrite(ULONG Offset,
-                     ULONG Value)
-{
-   PULONG p;
-   ULONG CPU = (_APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
-
-   lastregw[CPU] = Offset;
-   lastvalw[CPU] = Value;
-
-   p = (PULONG)((ULONG)APICBase + Offset);
-
-   *p = Value;
-}
-#endif
-
-
-#if 0
-inline ULONG APICRead(ULONG Offset)
-{
-   PULONG p;
-
-   p = (PULONG)((ULONG)APICBase + Offset);
-   return *p;
-}
-#else
-inline ULONG APICRead(ULONG Offset)
-{
-   PULONG p;
-   ULONG CPU = (_APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
-
-   lastregr[CPU] = Offset;
-   lastvalr[CPU] = 0;
-
-   p = (PULONG)((ULONG)APICBase + Offset);
-
-   lastvalr[CPU] = *p;
-   return lastvalr[CPU];
-}
-#endif
-
-inline VOID APICSendEOI(VOID)
-{
-  // Send the EOI
-  APICWrite(APIC_EOI, 0);
-}
-
 static VOID APICDumpBit(ULONG base)
 {
        ULONG v, i, j;
@@ -319,8 +250,7 @@ VOID APICDump(VOID)
 {
   ULONG v, ver, maxlvt;
   ULONG r1, r2, w1, w2;
-  ULONG CPU = ThisCPU();;
-
+  ULONG CPU = ThisCPU();
 
 
   r1 = lastregr[CPU];
@@ -420,7 +350,8 @@ VOID APICDump(VOID)
 
 BOOLEAN VerifyLocalAPIC(VOID)
 {
-   UINT reg0, reg1;
+   SIZE_T reg0, reg1;
+   ULONG l = 0, h = 0;
    /* The version register is read-only in a real APIC */
    reg0 = APICRead(APIC_VER);
    DPRINT1("Getting VERSION: %x\n", reg0);
@@ -467,15 +398,14 @@ BOOLEAN VerifyLocalAPIC(VOID)
       return FALSE;
    }
 
-   ULONG l, h;
-   Ki386Rdmsr(0x1b /*MSR_IA32_APICBASE*/, l, h);
+   Ke386Rdmsr(0x1b /*MSR_IA32_APICBASE*/, l, h);
 
    if (!(l & /*MSR_IA32_APICBASE_ENABLE*/(1<<11))) 
    {
       DPRINT1("Local APIC disabled by BIOS -- reenabling.\n");
       l &= ~/*MSR_IA32_APICBASE_BASE*/(1<<11);
       l |= /*MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE*/(1<<11)|0xfee00000;
-      Ki386Wrmsr(0x1b/*MSR_IA32_APICBASE*/, l, h);
+      Ke386Wrmsr(0x1b/*MSR_IA32_APICBASE*/, l, h);
    }
 
     
@@ -486,11 +416,11 @@ BOOLEAN VerifyLocalAPIC(VOID)
 #ifdef CONFIG_SMP
 VOID APICSendIPI(ULONG Target, ULONG Mode)
 {
-   ULONG tmp, i, flags;
+   ULONG tmp, i, flags = 0;
 
    /* save flags and disable interrupts */
-   Ki386SaveFlags(flags);
-   Ki386DisableInterrupts();
+   Ke386SaveFlags(flags);
+   _disable();
 
    /* Wait up to 100ms for the APIC to become ready */
    for (i = 0; i < 10000; i++) 
@@ -545,7 +475,7 @@ VOID APICSendIPI(ULONG Target, ULONG Mode)
    {
       DPRINT1("CPU(%d) Current IPI was not delivered after 100ms.\n", ThisCPU());
    }
-   Ki386RestoreFlags(flags);
+   Ke386RestoreFlags(flags);
 }
 #endif
 
@@ -754,10 +684,10 @@ VOID MpsIpiHandler(VOID)
 {
    KIRQL oldIrql;
 
-   HalBeginSystemInterrupt(IPI_VECTOR, 
-                           IPI_LEVEL
+   HalBeginSystemInterrupt(IPI_LEVEL,
+                           IPI_VECTOR
                           &oldIrql);
-   Ki386EnableInterrupts();
+   _enable();
 #if 0
    DbgPrint("(%s:%d) MpsIpiHandler on CPU%d, current irql is %d\n", 
             __FILE__,__LINE__, KeGetCurrentProcessorNumber(), KeGetCurrentIrql());
@@ -769,7 +699,7 @@ VOID MpsIpiHandler(VOID)
    DbgPrint("(%s:%d) MpsIpiHandler on CPU%d done\n", __FILE__,__LINE__, KeGetCurrentProcessorNumber());
 #endif
 
-   Ki386DisableInterrupts();
+   _disable();
    HalEndSystemInterrupt(oldIrql, 0);
 }
 #endif
@@ -778,21 +708,25 @@ VOID
 MpsIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
                           PKTRAP_FRAME TrapFrame)
 {
-   TrapFrame->Gs     = (USHORT)IrqTrapFrame->Gs;
-   TrapFrame->Fs     = (USHORT)IrqTrapFrame->Fs;
-   TrapFrame->Es     = (USHORT)IrqTrapFrame->Es;
-   TrapFrame->Ds     = (USHORT)IrqTrapFrame->Ds;
+#ifdef _M_AMD64
+    UNIMPLEMENTED;
+#else
+   TrapFrame->SegGs     = (USHORT)IrqTrapFrame->Gs;
+   TrapFrame->SegFs     = (USHORT)IrqTrapFrame->Fs;
+   TrapFrame->SegEs     = (USHORT)IrqTrapFrame->Es;
+   TrapFrame->SegDs     = (USHORT)IrqTrapFrame->Ds;
    TrapFrame->Eax    = IrqTrapFrame->Eax;
    TrapFrame->Ecx    = IrqTrapFrame->Ecx;
    TrapFrame->Edx    = IrqTrapFrame->Edx;
    TrapFrame->Ebx    = IrqTrapFrame->Ebx;
-   TrapFrame->Esp    = IrqTrapFrame->Esp;
+   TrapFrame->HardwareEsp    = IrqTrapFrame->Esp;
    TrapFrame->Ebp    = IrqTrapFrame->Ebp;
    TrapFrame->Esi    = IrqTrapFrame->Esi;
    TrapFrame->Edi    = IrqTrapFrame->Edi;
    TrapFrame->Eip    = IrqTrapFrame->Eip;
-   TrapFrame->Cs     = IrqTrapFrame->Cs;
-   TrapFrame->Eflags = IrqTrapFrame->Eflags;
+   TrapFrame->SegCs     = IrqTrapFrame->Cs;
+   TrapFrame->EFlags = IrqTrapFrame->Eflags;
+#endif
 }
 
 VOID
@@ -807,28 +741,29 @@ MpsTimerHandler(ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
    HalBeginSystemInterrupt(LOCAL_TIMER_VECTOR, 
                            PROFILE_LEVEL, 
                           &oldIrql);
-   Ki386EnableInterrupts();
+   _enable();
 
 #if 0
    CPU = ThisCPU();
    if ((Count[CPU] % 100) == 0)
    {
-     DbgPrint("(%s:%d) MpsTimerHandler on CPU%d, irql = %d, epi = %x, KPCR = %x\n", __FILE__, __LINE__, CPU, oldIrql,Trapframe->Eip, KeGetCurrentKPCR());
+     DbgPrint("(%s:%d) MpsTimerHandler on CPU%d, irql = %d, epi = %x, KPCR = %x\n", __FILE__, __LINE__, CPU, oldIrql,Trapframe->Eip, KeGetPcr());
    }
    Count[CPU]++;
 #endif
 
+   /* FIXME: SMP is totally broken */
    MpsIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
    if (KeGetCurrentProcessorNumber() == 0)
    {
-      KeUpdateSystemTime(&KernelTrapFrame, oldIrql);
+      //KeUpdateSystemTime(&KernelTrapFrame, oldIrql);
    }
    else
    {
-      KeUpdateRunTime(&KernelTrapFrame, oldIrql);
+      //KeUpdateRunTime(&KernelTrapFrame, oldIrql);
    }
 
-   Ki386DisableInterrupts();
+   _disable();
    HalEndSystemInterrupt (oldIrql, 0);
 }
 
@@ -839,12 +774,12 @@ VOID APICSetupLVTT(ULONG ClockTicks)
    tmp = GET_APIC_VERSION(APICRead(APIC_VER));
    if (!APIC_INTEGRATED(tmp))
    {
-      tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;;
+      tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;
    }
    else
    {
       /* Periodic timer */
-      tmp = APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;;
+      tmp = APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;
    }
    APICWrite(APIC_LVTT, tmp);
 
@@ -866,36 +801,36 @@ APICCalibrateTimer(ULONG CPU)
 
    APICSetupLVTT(1000000000);
 
-   TSCPresent = KeGetCurrentKPCR()->PrcbData.FeatureBits & X86_FEATURE_TSC ? TRUE : FALSE;
+   TSCPresent = KeGetCurrentPrcb()->FeatureBits & KF_RDTSC ? TRUE : FALSE;
 
    /*
     * The timer chip counts down to zero. Let's wait
     * for a wraparound to start exact measurement:
     * (the current tick might have been already half done)
     */
-   WaitFor8254Wraparound();
+   //WaitFor8254Wraparound();
 
    /*
     * We wrapped around just now. Let's start
     */
    if (TSCPresent)
    {
-      Ki386RdTSC(t1);
+      t1.QuadPart = (LONGLONG)__rdtsc();
    }
    tt1 = APICRead(APIC_CCRT);
 
-   WaitFor8254Wraparound();
+   //WaitFor8254Wraparound();
 
 
    tt2 = APICRead(APIC_CCRT);
    if (TSCPresent)
    {
-      Ki386RdTSC(t2);
+      t2.QuadPart = (LONGLONG)__rdtsc();
       CPUMap[CPU].CoreSpeed = (HZ * (t2.QuadPart - t1.QuadPart));
       DPRINT("CPU clock speed is %ld.%04ld MHz.\n",
             CPUMap[CPU].CoreSpeed/1000000,
             CPUMap[CPU].CoreSpeed%1000000);
-      KeGetCurrentKPCR()->PrcbData.MHz = CPUMap[CPU].CoreSpeed/1000000;
+      KeGetCurrentPrcb()->MHz = CPUMap[CPU].CoreSpeed/1000000;
    }
 
    CPUMap[CPU].BusSpeed = (HZ * (long)(tt1 - tt2) * APIC_DIVISOR);
@@ -911,13 +846,41 @@ APICCalibrateTimer(ULONG CPU)
 }
 
 VOID 
-SetInterruptGate(ULONG index, ULONG address)
+SetInterruptGate(ULONG index, ULONG_PTR address)
 {
-  IDT_DESCRIPTOR *idt;
-
-  idt = (IDT_DESCRIPTOR*)((ULONG)KeGetCurrentKPCR()->IDT + index * sizeof(IDT_DESCRIPTOR));
-  idt->a = (((ULONG)address)&0xffff) + (KERNEL_CS << 16);
-  idt->b = 0x8e00 + (((ULONG)address)&0xffff0000);
+#ifdef _M_AMD64
+  KIDTENTRY64 *idt;
+
+  idt = &KeGetPcr()->IdtBase[index];
+
+  idt->OffsetLow = address & 0xffff;
+  idt->Selector = KGDT_64_R0_CODE;
+  idt->IstIndex = 0;
+  idt->Reserved0 = 0;
+  idt->Type = 0x0e;
+  idt->Dpl = 0;
+  idt->Present = 1;
+  idt->OffsetMiddle = (address >> 16) & 0xffff;
+  idt->OffsetHigh = address >> 32;
+  idt->Reserved1 = 0;
+  idt->Alignment = 0;
+#else
+  KIDTENTRY *idt;
+  KIDT_ACCESS Access;
+
+  /* Set the IDT Access Bits */
+  Access.Reserved = 0;
+  Access.Present = 1;
+  Access.Dpl = 0; /* Kernel-Mode */
+  Access.SystemSegmentFlag = 0;
+  Access.SegmentType = I386_INTERRUPT_GATE;
+  
+  idt = (KIDTENTRY*)((ULONG)KeGetPcr()->IDT + index * sizeof(KIDTENTRY));
+  idt->Offset = address & 0xffff;
+  idt->Selector = KGDT_R0_CODE;
+  idt->Access = Access.Value;
+  idt->ExtendedOffset = address >> 16;
+#endif
 }
 
 VOID HaliInitBSP(VOID)
@@ -931,20 +894,20 @@ VOID HaliInitBSP(VOID)
    /* Only initialize the BSP once */
    if (BSPInitialized)
    {
-      KEBUGCHECK(0);
+      ASSERT(FALSE);
       return;
    }
 
    BSPInitialized = TRUE;
 
    /* Setup interrupt handlers */
-   SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG)MpsTimerInterrupt);
-   SetInterruptGate(ERROR_VECTOR, (ULONG)MpsErrorInterrupt);
-   SetInterruptGate(SPURIOUS_VECTOR, (ULONG)MpsSpuriousInterrupt);
+   SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG_PTR)MpsTimerInterrupt);
+   SetInterruptGate(ERROR_VECTOR, (ULONG_PTR)MpsErrorInterrupt);
+   SetInterruptGate(SPURIOUS_VECTOR, (ULONG_PTR)MpsSpuriousInterrupt);
 #ifdef CONFIG_SMP
-   SetInterruptGate(IPI_VECTOR, (ULONG)MpsIpiInterrupt);
+   SetInterruptGate(IPI_VECTOR, (ULONG_PTR)MpsIpiInterrupt);
 #endif
-   DPRINT("APIC is mapped at 0x%X\n", APICBase);
+   DPRINT1("APIC is mapped at 0x%p\n", (PVOID)APICBase);
 
    if (VerifyLocalAPIC()) 
    {
@@ -952,8 +915,8 @@ VOID HaliInitBSP(VOID)
    } 
    else 
    {
-      DPRINT("No APIC found\n");
-      KEBUGCHECK(0);
+      DPRINT1("No APIC found\n");
+      ASSERT(FALSE);
    }
 
    if (APICMode == amPIC) 
@@ -971,18 +934,18 @@ VOID HaliInitBSP(VOID)
    CommonBase = (PULONG)COMMON_AREA;
  
    /* Copy bootstrap code to common area */
-   memcpy((PVOID)((ULONG)CommonBase + PAGE_SIZE),
+   memcpy((PVOID)((ULONG_PTR)CommonBase + PAGE_SIZE),
          &APstart,
-         (ULONG)&APend - (ULONG)&APstart + 1);
+         (ULONG_PTR)&APend - (ULONG_PTR)&APstart + 1);
 
    /* Set shutdown code */
    CMOS_WRITE(0xF, 0xA);
 
    /* Set warm reset vector */
-   ps = (PUSHORT)((ULONG)BIOSBase + 0x467);
+   ps = (PUSHORT)((ULONG_PTR)BIOSBase + 0x467);
    *ps = (COMMON_AREA + PAGE_SIZE) & 0xF;
  
-   ps = (PUSHORT)((ULONG)BIOSBase + 0x469);
+   ps = (PUSHORT)((ULONG_PTR)BIOSBase + 0x469);
    *ps = (COMMON_AREA + PAGE_SIZE) >> 4;
 #endif
 
@@ -1005,7 +968,7 @@ HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack)
        Cpu >= CPUCount ||
        OnlineCPUs & (1 << Cpu))
    {
-     KEBUGCHECK(0);
+     ASSERT(FALSE);
    }
    DPRINT1("Attempting to boot CPU %d\n", Cpu);
 
@@ -1031,11 +994,11 @@ HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack)
    /* Write the location of the AP stack */
    Common->Stack = (ULONG)Stack;
    /* Write the page directory page */
-   Ke386GetPageTableDirectory(Common->PageDirectory);
+   Common->PageDirectory = __readcr3();
    /* Write the kernel entry point */
-   Common->NtProcessStartup = (ULONG_PTR)RtlImageNtHeader(MmSystemRangeStart)->OptionalHeader.AddressOfEntryPoint + (ULONG_PTR)MmSystemRangeStart;
+   Common->NtProcessStartup = (ULONG_PTR)RtlImageNtHeader((PVOID)KernelBase)->OptionalHeader.AddressOfEntryPoint + KernelBase;
    /* Write the state of the mae mode */
-   Common->PaeModeEnabled = Ke386GetCr4() & X86_CR4_PAE ? 1 : 0;
+   Common->PaeModeEnabled = __readcr4() & CR4_PAE ? 1 : 0;
 
    DPRINT1("%x %x %x %x\n", Common->Stack, Common->PageDirectory, Common->NtProcessStartup, Common->PaeModeEnabled);