We now have a good initialization routine for ARM. We call HalInitializeProcessor...
authorReactOS Portable Systems Group <ros-arm-bringup@svn.reactos.org>
Tue, 12 Feb 2008 22:50:54 +0000 (22:50 +0000)
committerReactOS Portable Systems Group <ros-arm-bringup@svn.reactos.org>
Tue, 12 Feb 2008 22:50:54 +0000 (22:50 +0000)
There's now a cpu.c for ARM as well, and the cache routines are now there.
KDCOM APIs were marked as kernel stubs, so the kernel was never linking with kdcom. This has been fixed, and boot now stops in kdcom!KdPortInitializeEx since there's no ARM-compatible code.

svn path=/trunk/; revision=32334

reactos/drivers/base/kdcom/kdbg.c
reactos/include/ndk/arm/ketypes.h
reactos/include/reactos/armddk.h
reactos/ntoskrnl/include/internal/arm/ke.h
reactos/ntoskrnl/ke/arm/cpu.c [new file with mode: 0644]
reactos/ntoskrnl/ke/arm/kiinit.c
reactos/ntoskrnl/ke/arm/stubs_asm.s
reactos/ntoskrnl/ntoskrnl.rbuild

index b07de7c..5c457b9 100644 (file)
@@ -250,6 +250,11 @@ KdPortInitializeEx(
     ULONG divisor;
     UCHAR lcr;
 
+#ifdef _ARM_
+    UNIMPLEMENTED;
+    while (TRUE);
+#endif
+
     if (PortInformation->BaudRate == 0)
         PortInformation->BaudRate = DEFAULT_BAUD_RATE;
 
index 9ab0e53..fca321c 100644 (file)
@@ -135,6 +135,7 @@ typedef struct _KPRCB
     UCHAR NodeColor;
     UCHAR Spare1;
     ULONG NodeShiftedColor;
+    ULONG PcrPage;
     struct _KNODE *ParentNode;
     ULONG MultiThreadProcessorSet;
     struct _KPRCB *MultiThreadSetMaster;
index 1144962..1651207 100644 (file)
 #define PCR                     ((volatile KPCR * const)USPCR)
 #define USERPCR                 ((volatile KPCR * const)KIPCR)
 
+//
+// Maximum IRQs
+//
+#define MAXIMUM_VECTOR          16
+
 //
 // Just read it from the PCR
 //
@@ -46,7 +51,7 @@ typedef struct _KPCR
 {
     ULONG MinorVersion;
     ULONG MajorVersion;
-    PKINTERRUPT_ROUTINE InterruptRoutine[16];
+    PKINTERRUPT_ROUTINE InterruptRoutine[MAXIMUM_VECTOR];
     PVOID XcodeDispatch;
     ULONG FirstLevelDcacheSize;
     ULONG FirstLevelDcacheFillSize;
@@ -77,6 +82,7 @@ typedef struct _KPCR
     UCHAR CurrentIrql;
     KAFFINITY SetMember;
     struct _KTHREAD *CurrentThread;
+    ULONG ReservedVectors;
     KAFFINITY NotMember;
     ULONG SystemReserved[6];
     ULONG DcacheAlignment;
@@ -127,4 +133,17 @@ KeRaiseIrqlToDpcLevel(
 #define KeLowerIrql(NewIrql) KeSwapIrql(NewIrql)
 #define KeRaiseIrql(NewIrql, OldIrql) *(OldIrql) = KeSwapIrql(NewIrql)
 
+//
+// Cache clean and flush
+//
+VOID
+HalSweepDcache(
+    VOID
+);
+
+VOID
+HalSweepIcache(
+    VOID
+);
+
 #endif
index 019c215..a8f150f 100644 (file)
@@ -148,6 +148,31 @@ KeArmInitThreadWithContext(
     IN PCONTEXT Context
 );
 
+VOID
+KiPassiveRelease(
+    VOID
+
+);
+
+VOID
+KiApcInterrupt(
+    VOID                 
+);
+
+#include "mm.h"
+
+VOID
+KeFillFixedEntryTb(
+    IN ARM_PTE Pte,
+    IN PVOID Virtual,
+    IN ULONG Index
+);
+
+VOID
+KeFlushTb(
+    VOID
+);
+
 #define KeArchInitThreadWithContext KeArmInitThreadWithContext
 
 #endif
diff --git a/reactos/ntoskrnl/ke/arm/cpu.c b/reactos/ntoskrnl/ke/arm/cpu.c
new file mode 100644 (file)
index 0000000..03353a6
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/ke/arm/cpu.c
+ * PURPOSE:         Implements routines for ARM CPU support
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+ULONG KeFixedTbEntries;
+ULONG KiDmaIoCoherency;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+KiFlushSingleTb(IN BOOLEAN Invalid,
+                IN PVOID Virtual)
+{
+    //
+    // Just invalidate it
+    //
+    KeArmInvalidateTlbEntry(Virtual);
+}
+
+VOID
+KeFillFixedEntryTb(IN ARM_PTE Pte,
+                   IN PVOID Virtual,
+                   IN ULONG Index)
+{
+    ARM_LOCKDOWN_REGISTER LockdownRegister;
+    ULONG OldVictimCount;
+    volatile unsigned long Temp;
+    PARM_TRANSLATION_TABLE TranslationTable;
+    
+    //
+    // Hack for 1MB Section Entries
+    //
+    Virtual = (PVOID)((ULONG)Virtual & 0xFFF00000);
+    
+    //
+    // On ARM, we can't set the index ourselves, so make sure that we are not
+    // locking down more than 8 entries.
+    //
+    UNREFERENCED_PARAMETER(Index);
+    KeFixedTbEntries++;
+    ASSERT(KeFixedTbEntries <= 8);
+    
+    //
+    // Flush the address
+    //
+    KiFlushSingleTb(TRUE, Virtual);
+    
+    //
+    // Read lockdown register and set the preserve bit
+    //
+    LockdownRegister = KeArmLockdownRegisterGet();
+    LockdownRegister.Preserve = TRUE;
+    OldVictimCount = LockdownRegister.Victim;
+    KeArmLockdownRegisterSet(LockdownRegister);
+    
+    //
+    // Map the PTE for this virtual address
+    //
+    TranslationTable = (PVOID)KeArmTranslationTableRegisterGet().AsUlong;
+    TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT] = Pte;
+    
+    //
+    // Now force a miss
+    //
+    Temp = *(PULONG)Virtual;
+    
+    //
+    // Read lockdown register 
+    //
+    LockdownRegister = KeArmLockdownRegisterGet();
+    if (LockdownRegister.Victim == 0)
+    {
+        //
+        // This can only happen on QEMU or broken CPUs since there *has*
+        // to have been at least a miss since the system started. For example,
+        // QEMU doesn't support TLB lockdown.
+        //
+        // On these systems, we'll just keep the PTE mapped
+        //
+        DPRINT1("TLB Lockdown Failure (%p). Running on QEMU?\n", Virtual);
+    }
+    else
+    {
+        //
+        // Clear the preserve bits
+        //
+        LockdownRegister.Preserve = FALSE;
+        ASSERT(LockdownRegister.Victim == OldVictimCount + 1);
+        KeArmLockdownRegisterSet(LockdownRegister);
+        
+        //
+        // Clear the PTE
+        //
+        TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT].AsUlong = 0;
+    }
+}
+
+VOID
+KeFlushTb(VOID)
+{
+    //
+    // Flush the entire TLB
+    //
+    KeArmFlushTlb();
+}
index 55f9b19..8e91e71 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
+KINTERRUPT KxUnexpectedInterrupt;
 BOOLEAN KeIsArmV6;
-ULONG KeFixedTbEntries;
 ULONG KeNumberProcessIds;
 ULONG KeNumberTbEntries;
-
-VOID HalSweepDcache(VOID);
-VOID HalSweepIcache(VOID);
-
 #define __ARMV6__ KeIsArmV6
 
 //
@@ -45,140 +41,173 @@ DebugService(IN ULONG ServiceType,
 }
 
 VOID
-KiFlushSingleTb(IN BOOLEAN Invalid,
-                IN PVOID Virtual)
+NTAPI
+KiInitializeKernel(IN PKPROCESS InitProcess,
+                   IN PKTHREAD InitThread,
+                   IN PVOID IdleStack,
+                   IN PKPRCB Prcb,
+                   IN CCHAR Number,
+                   IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-    //
-    // Just invalidate it
-    //
-    KeArmInvalidateTlbEntry(Virtual);
-}
+    LARGE_INTEGER PageDirectory;
+    PKPCR Pcr;
+    ULONG i;
+    DPRINT1("%s Process: %p Thread: %p Stack: %p PRCB: %p Number: %d LoaderBlock: %p\n",
+            __FUNCTION__, InitProcess, InitThread, IdleStack, Prcb, Number, LoaderBlock);
 
-VOID
-KeFillFixedEntryTb(IN ARM_PTE Pte,
-                   IN PVOID Virtual,
-                   IN ULONG Index)
-{
-    ARM_LOCKDOWN_REGISTER LockdownRegister;
-    ULONG OldVictimCount;
-    volatile unsigned long Temp;
-    PARM_TRANSLATION_TABLE TranslationTable;
-    
     //
-    // Hack for 1MB Section Entries
+    // Initialize the platform
     //
-    Virtual = (PVOID)((ULONG)Virtual & 0xFFF00000);
+    HalInitializeProcessor(Number, LoaderBlock);
     
     //
-    // On ARM, we can't set the index ourselves, so make sure that we are not
-    // locking down more than 8 entries.
+    // Save loader block
     //
-    UNREFERENCED_PARAMETER(Index);
-    KeFixedTbEntries++;
-    ASSERT(KeFixedTbEntries <= 8);
-    
+    KeLoaderBlock = LoaderBlock;
+
     //
-    // Flush the address
+    // Setup KPRCB
+    //
+    Prcb->MajorVersion = 1;
+    Prcb->MinorVersion = 1;
+    Prcb->BuildType = 0;
+#ifndef CONFIG_SMP
+    Prcb->BuildType |= PRCB_BUILD_UNIPROCESSOR;
+#endif
+#ifdef DBG
+    Prcb->BuildType |= PRCB_BUILD_DEBUG;
+#endif
+    Prcb->CurrentThread = InitThread;
+    Prcb->NextThread = NULL;
+    Prcb->IdleThread = InitThread;
+    Prcb->Number = Number;
+    Prcb->SetMember = 1 << Number;
+    Prcb->PcrPage = LoaderBlock->u.Arm.PcrPage;
+
     //
-    KiFlushSingleTb(TRUE, Virtual);
-    
+    // Initialize spinlocks and DPC data
     //
-    // Read lockdown register and set the preserve bit
+    KiInitSpinLocks(Prcb, Number);
+
     //
-    LockdownRegister = KeArmLockdownRegisterGet();
-    LockdownRegister.Preserve = TRUE;
-    OldVictimCount = LockdownRegister.Victim;
-    KeArmLockdownRegisterSet(LockdownRegister);
-    
+    // Set the PRCB in the processor block
     //
-    // Map the PTE for this virtual address
+    KiProcessorBlock[(ULONG)Number] = Prcb;
+    Pcr = (PKPCR)KeGetPcr();
+
     //
-    TranslationTable = (PVOID)KeArmTranslationTableRegisterGet().AsUlong;
-    TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT] = Pte;
-    
+    // Set processor information
     //
-    // Now force a miss
+    KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM;
+    KeFeatureBits = 0;
+    KeProcessorLevel = (USHORT)(Pcr->ProcessorId >> 8);
+    KeProcessorRevision = (USHORT)(Pcr->ProcessorId & 0xFF);
+
     //
-    Temp = *(PULONG)Virtual;
-    
+    // Set stack pointers
     //
-    // Read lockdown register 
+    Pcr->InitialStack = IdleStack;
+    Pcr->StackLimit = (PVOID)((ULONG_PTR)IdleStack - KERNEL_STACK_SIZE);
+
     //
-    LockdownRegister = KeArmLockdownRegisterGet();
-    if (LockdownRegister.Victim == 0)
+    // Check if this is the Boot CPU
+    //
+    if (!Number)
     {
         //
-        // This can only happen on QEMU or broken CPUs since there *has*
-        // to have been at least a miss since the system started. For example,
-        // QEMU doesn't support TLB lockdown.
+        // Setup the unexpected interrupt
         //
-        // On these systems, we'll just keep the PTE mapped
-        //
-        DPRINT1("TLB Lockdown Failure (%p). Running on QEMU?\n", Virtual);
-    }
-    else
-    {
+        KxUnexpectedInterrupt.DispatchAddress = KiUnexpectedInterrupt;
+        for (i = 0; i < 4; i++)
+        {
+            //
+            // Copy the template code
+            //
+            KxUnexpectedInterrupt.DispatchCode[i] = KiInterruptTemplate[i];
+        }
+        
         //
-        // Clear the preserve bits
+        // Set DMA coherency
         //
-        LockdownRegister.Preserve = FALSE;
-        ASSERT(LockdownRegister.Victim == OldVictimCount + 1);
-        KeArmLockdownRegisterSet(LockdownRegister);
+        KiDmaIoCoherency = 0;
         
         //
-        // Clear the PTE
+        // Sweep D-Cache
         //
-        TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT].AsUlong = 0;
+        HalSweepDcache();
     }
-}
+    
+    //
+    // Set all interrupt routines to unexpected interrupts as well
+    //
+    for (i = 0; i < MAXIMUM_VECTOR; i++)
+    {
+        //
+        // Point to the same template
+        //
+        Pcr->InterruptRoutine[i] = &KxUnexpectedInterrupt.DispatchCode;
+    }
+    
+    //
+    // Setup profiling
+    //
+    Pcr->ProfileCount = 0;
+    Pcr->ProfileInterval = 0x200000;
+    Pcr->StallScaleFactor = 50;
+    
+    //
+    // Setup software interrupts
+    //
+    Pcr->InterruptRoutine[PASSIVE_LEVEL] = KiPassiveRelease;
+    Pcr->InterruptRoutine[APC_LEVEL] = KiApcInterrupt;
+    Pcr->InterruptRoutine[DISPATCH_LEVEL] = KiDispatchInterrupt;
+    Pcr->ReservedVectors = (1 << PASSIVE_LEVEL) |
+                           (1 << APC_LEVEL) |
+                           (1 << DISPATCH_LEVEL) |
+                           (1 << IPI_LEVEL);
 
-VOID
-KeFlushTb(VOID)
-{
     //
-    // Flush the entire TLB
+    // Set IRQL and prcessor member/number
     //
-    KeArmFlushTlb();
-}
+    Pcr->CurrentIrql = APC_LEVEL;
+    Pcr->SetMember = 1 << Number;
+    Pcr->NotMember = -Pcr->SetMember;
+    Pcr->Number = Number;
 
-VOID
-NTAPI
-KiInitializeKernel(IN PKPROCESS InitProcess,
-                   IN PKTHREAD InitThread,
-                   IN PVOID IdleStack,
-                   IN PKPRCB Prcb,
-                   IN CCHAR Number,
-                   IN PLOADER_PARAMETER_BLOCK LoaderBlock)
-{
-    LARGE_INTEGER PageDirectory;
-    PVOID DpcStack;
-    DPRINT1("%s Process: %p Thread: %p Stack: %p PRCB: %p Number: %d LoaderBlock: %p\n",
-            __FUNCTION__, InitProcess, InitThread, IdleStack, Prcb, Number, LoaderBlock);
+    //
+    // Remember our parent
+    //
+    InitThread->ApcState.Process = InitProcess;
 
-    /* Initialize the Power Management Support for this PRCB */
-    PoInitializePrcb(Prcb);
-    
-    /* Save CPU state */
-    KiSaveProcessorControlState(&Prcb->ProcessorState);
-    
-    /* Initialize spinlocks and DPC data */
-    KiInitSpinLocks(Prcb, Number);
-    
-    /* Check if this is the Boot CPU */
+    //
+    // Setup the active processor numbers
+    //
+    KeActiveProcessors |= 1 << Number;
+    KeNumberProcessors = Number + 1;
+
+    //
+    // Check if this is the boot CPU
+    //
     if (!Number)
     {
-        /* Set Node Data */
-        KeNodeBlock[0] = &KiNode0;
-        Prcb->ParentNode = KeNodeBlock[0];
-        KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
-          
-        /* Lower to APC_LEVEL */
-        KeLowerIrql(APC_LEVEL);
-        
-        /* Initialize portable parts of the OS */
+        //
+        // Setup KD
+        //
+        KdInitSystem(0, LoaderBlock);
+
+        //
+        // Cleanup the rest of the processor block array
+        //
+        for (i = 1; i < MAXIMUM_PROCESSORS; i++) KiProcessorBlock[i] = NULL;
+
+        //
+        // Initialize portable parts of the OS
+        //
         KiInitSystem();
-        
-        /* Initialize the Idle Process and the Process Listhead */
+
+        //
+        // Initialize the Idle Process and the Process Listhead
+        //
         InitializeListHead(&KiProcessListHead);
         PageDirectory.QuadPart = 0;
         KeInitializeProcess(InitProcess,
@@ -190,11 +219,15 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
     }
     else
     {
-        /* FIXME */
-        DPRINT1("SMP Boot support not yet present\n");
+        //
+        // FIXME
+        //
+        DPRINT1("ARM MPCore not supported\n");
     }
     
-    /* Setup the Idle Thread */
+    //
+    // Setup the Idle Thread
+    //
     KeInitializeThread(InitProcess,
                        InitThread,
                        NULL,
@@ -209,61 +242,68 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
     InitThread->Affinity = 1 << Number;
     InitThread->WaitIrql = DISPATCH_LEVEL;
     InitProcess->ActiveProcessors = 1 << Number;
-    
-    /* HACK for MmUpdatePageDir */
+
+    //
+    // HACK for MmUpdatePageDir
+    //
     ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
-    
-    /* Initialize Kernel Memory Address Space */
+
+    //
+    // Initialize Kernel Memory Address Space
+    //
     MmInit1(MmFreeLdrFirstKrnlPhysAddr,
             MmFreeLdrLastKrnlPhysAddr,
             MmFreeLdrLastKernelAddress,
             NULL,
             0,
             4096);
-    
-    /* Set basic CPU Features that user mode can read */
-    
-    /* Set up the thread-related fields in the PRCB */
-    Prcb->CurrentThread = InitThread;
-    Prcb->NextThread = NULL;
-    Prcb->IdleThread = InitThread;
-    
-    /* Initialize the Kernel Executive */
+
+    //
+    // Initialize the Kernel Executive
+    //
     ExpInitializeExecutive(Number, LoaderBlock);
     
-    /* Only do this on the boot CPU */
+    //
+    // Only do this on the boot CPU
+    //
     if (!Number)
     {
-        /* Calculate the time reciprocal */
+        //
+        // Calculate the time reciprocal
+        //
         KiTimeIncrementReciprocal =
         KiComputeReciprocal(KeMaximumIncrement,
                             &KiTimeIncrementShiftCount);
         
-        /* Update DPC Values in case they got updated by the executive */
+        //
+        // Update DPC Values in case they got updated by the executive
+        //
         Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
         Prcb->MinimumDpcRate = KiMinimumDpcRate;
         Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
-        
-        /* Allocate the DPC Stack */
-        DpcStack = MmCreateKernelStack(FALSE, 0);
-        if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
-        Prcb->DpcStack = DpcStack;
     }
     
-    /* Raise to Dispatch */
+    //
+    // Raise to Dispatch
+    //
     KeSwapIrql(DISPATCH_LEVEL);
     
-    /* Set the Idle Priority to 0. This will jump into Phase 1 */
+    //
+    // Set the Idle Priority to 0. This will jump into Phase 1
+    //
     KeSetPriorityThread(InitThread, 0);
     
-    /* If there's no thread scheduled, put this CPU in the Idle summary */
+    //
+    // If there's no thread scheduled, put this CPU in the Idle summary
+    //
     KiAcquirePrcbLock(Prcb);
     if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
     KiReleasePrcbLock(Prcb);
     
-    /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
+    //
+    // Raise back to HIGH_LEVEL
+    //
     KeSwapIrql(HIGH_LEVEL);
-    LoaderBlock->Prcb = 0;
 }
 
 VOID
index 94dc9aa..e3e11ca 100644 (file)
@@ -62,6 +62,9 @@ GENERATE_ARM_STUB KeUserModeCallback
 GENERATE_ARM_STUB Kei386EoiHelper 
 GENERATE_ARM_STUB KiCoprocessorError 
 GENERATE_ARM_STUB KiDispatchInterrupt 
+GENERATE_ARM_STUB KiApcInterrupt 
+GENERATE_ARM_STUB KiPassiveRelease 
+GENERATE_ARM_STUB KiInterruptTemplate 
 GENERATE_ARM_STUB KiUnexpectedInterrupt  
 GENERATE_ARM_STUB MmGetPhysicalAddress 
 GENERATE_ARM_STUB NtVdmControl 
@@ -122,7 +125,6 @@ GENERATE_ARM_STUB MmGetPfnForProcess
 GENERATE_ARM_STUB MmCreateVirtualMapping
 GENERATE_ARM_STUB CmpInitializeMachineDependentConfiguration
 GENERATE_ARM_STUB KeI386VdmInitialize
-GENERATE_ARM_STUB KdDebuggerInitialize1
 GENERATE_ARM_STUB MmSetDirtyPage
 GENERATE_ARM_STUB MmSetCleanPage
 GENERATE_ARM_STUB MmIsDirtyPage
@@ -146,8 +148,6 @@ GENERATE_ARM_STUB RtlInitializeContext
 GENERATE_ARM_STUB RtlpGetExceptionAddress
 GENERATE_ARM_STUB RtlDispatchException
 GENERATE_ARM_STUB DebugService2
-GENERATE_ARM_STUB KdPortPutByteEx
-GENERATE_ARM_STUB KdPortInitializeEx
 GENERATE_ARM_STUB KdpGdbStubInit
 GENERATE_ARM_STUB KeSwitchKernelStack
 GENERATE_ARM_STUB MiInitPageDirectoryMap
index c425aaa..3bc074a 100644 (file)
@@ -61,6 +61,7 @@
                        <directory name="arm">
                                <file first="true">boot.s</file>
                                <file>arm_kprintf.c</file>
+                               <file>cpu.c</file>
                                <file>kiinit.c</file>
                                <file>stubs_asm.s</file>
                                <file>stubs.c</file>