Author: ros-arm-bringup
Date: Wed Feb 13 01:50:54 2008
New Revision: 32334
URL:
http://svn.reactos.org/svn/reactos?rev=32334&view=rev
Log:
We now have a good initialization routine for ARM. We call HalInitializeProcessor (TBD) to
setup the board, then we configure the PRCB and PCR. We also setup some global CPU
variables and setup minimal interrupt support. The rest of the code follows the x86 design
(Create initial thread/process).
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.
Added:
trunk/reactos/ntoskrnl/ke/arm/cpu.c (with props)
Modified:
trunk/reactos/drivers/base/kdcom/kdbg.c
trunk/reactos/include/ndk/arm/ketypes.h
trunk/reactos/include/reactos/armddk.h
trunk/reactos/ntoskrnl/include/internal/arm/ke.h
trunk/reactos/ntoskrnl/ke/arm/kiinit.c
trunk/reactos/ntoskrnl/ke/arm/stubs_asm.s
trunk/reactos/ntoskrnl/ntoskrnl.rbuild
Modified: trunk/reactos/drivers/base/kdcom/kdbg.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdcom/kdbg.c?…
==============================================================================
--- trunk/reactos/drivers/base/kdcom/kdbg.c (original)
+++ trunk/reactos/drivers/base/kdcom/kdbg.c Wed Feb 13 01:50:54 2008
@@ -250,6 +250,11 @@
ULONG divisor;
UCHAR lcr;
+#ifdef _ARM_
+ UNIMPLEMENTED;
+ while (TRUE);
+#endif
+
if (PortInformation->BaudRate == 0)
PortInformation->BaudRate = DEFAULT_BAUD_RATE;
Modified: trunk/reactos/include/ndk/arm/ketypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/arm/ketypes.h?…
==============================================================================
--- trunk/reactos/include/ndk/arm/ketypes.h (original)
+++ trunk/reactos/include/ndk/arm/ketypes.h Wed Feb 13 01:50:54 2008
@@ -135,6 +135,7 @@
UCHAR NodeColor;
UCHAR Spare1;
ULONG NodeShiftedColor;
+ ULONG PcrPage;
struct _KNODE *ParentNode;
ULONG MultiThreadProcessorSet;
struct _KPRCB *MultiThreadSetMaster;
Modified: trunk/reactos/include/reactos/armddk.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/armddk.h?r…
==============================================================================
--- trunk/reactos/include/reactos/armddk.h (original)
+++ trunk/reactos/include/reactos/armddk.h Wed Feb 13 01:50:54 2008
@@ -23,6 +23,11 @@
#define USERPCR ((volatile KPCR * const)KIPCR)
//
+// Maximum IRQs
+//
+#define MAXIMUM_VECTOR 16
+
+//
// Just read it from the PCR
//
#define KeGetCurrentProcessorNumber() ((ULONG)(PCR->Number))
@@ -46,7 +51,7 @@
{
ULONG MinorVersion;
ULONG MajorVersion;
- PKINTERRUPT_ROUTINE InterruptRoutine[16];
+ PKINTERRUPT_ROUTINE InterruptRoutine[MAXIMUM_VECTOR];
PVOID XcodeDispatch;
ULONG FirstLevelDcacheSize;
ULONG FirstLevelDcacheFillSize;
@@ -77,6 +82,7 @@
UCHAR CurrentIrql;
KAFFINITY SetMember;
struct _KTHREAD *CurrentThread;
+ ULONG ReservedVectors;
KAFFINITY NotMember;
ULONG SystemReserved[6];
ULONG DcacheAlignment;
@@ -127,4 +133,17 @@
#define KeLowerIrql(NewIrql) KeSwapIrql(NewIrql)
#define KeRaiseIrql(NewIrql, OldIrql) *(OldIrql) = KeSwapIrql(NewIrql)
+//
+// Cache clean and flush
+//
+VOID
+HalSweepDcache(
+ VOID
+);
+
+VOID
+HalSweepIcache(
+ VOID
+);
+
#endif
Modified: trunk/reactos/ntoskrnl/include/internal/arm/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/arm/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/arm/ke.h Wed Feb 13 01:50:54 2008
@@ -148,6 +148,31 @@
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
Added: trunk/reactos/ntoskrnl/ke/arm/cpu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/cpu.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/arm/cpu.c (added)
+++ trunk/reactos/ntoskrnl/ke/arm/cpu.c Wed Feb 13 01:50:54 2008
@@ -1,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();
+}
Propchange: trunk/reactos/ntoskrnl/ke/arm/cpu.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/reactos/ntoskrnl/ke/arm/cpu.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: trunk/reactos/ntoskrnl/ke/arm/kiinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/kiinit.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/arm/kiinit.c (original)
+++ trunk/reactos/ntoskrnl/ke/arm/kiinit.c Wed Feb 13 01:50:54 2008
@@ -14,14 +14,10 @@
/* GLOBALS ********************************************************************/
+KINTERRUPT KxUnexpectedInterrupt;
BOOLEAN KeIsArmV6;
-ULONG KeFixedTbEntries;
ULONG KeNumberProcessIds;
ULONG KeNumberTbEntries;
-
-VOID HalSweepDcache(VOID);
-VOID HalSweepIcache(VOID);
-
#define __ARMV6__ KeIsArmV6
//
@@ -42,103 +38,6 @@
//
void arm_kprintf(const char *fmt, ...);
arm_kprintf("%s", Buffer);
-}
-
-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();
}
VOID
@@ -151,34 +50,164 @@
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
LARGE_INTEGER PageDirectory;
- PVOID DpcStack;
+ 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);
- /* Initialize the Power Management Support for this PRCB */
- PoInitializePrcb(Prcb);
-
- /* Save CPU state */
- KiSaveProcessorControlState(&Prcb->ProcessorState);
-
- /* Initialize spinlocks and DPC data */
+ //
+ // Initialize the platform
+ //
+ HalInitializeProcessor(Number, LoaderBlock);
+
+ //
+ // Save loader block
+ //
+ KeLoaderBlock = LoaderBlock;
+
+ //
+ // 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;
+
+ //
+ // Initialize spinlocks and DPC data
+ //
KiInitSpinLocks(Prcb, Number);
-
- /* Check if this is the Boot CPU */
+
+ //
+ // Set the PRCB in the processor block
+ //
+ KiProcessorBlock[(ULONG)Number] = Prcb;
+ Pcr = (PKPCR)KeGetPcr();
+
+ //
+ // Set processor information
+ //
+ KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM;
+ KeFeatureBits = 0;
+ KeProcessorLevel = (USHORT)(Pcr->ProcessorId >> 8);
+ KeProcessorRevision = (USHORT)(Pcr->ProcessorId & 0xFF);
+
+ //
+ // Set stack pointers
+ //
+ Pcr->InitialStack = IdleStack;
+ Pcr->StackLimit = (PVOID)((ULONG_PTR)IdleStack - KERNEL_STACK_SIZE);
+
+ //
+ // 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);
+ //
+ // Setup the unexpected interrupt
+ //
+ KxUnexpectedInterrupt.DispatchAddress = KiUnexpectedInterrupt;
+ for (i = 0; i < 4; i++)
+ {
+ //
+ // Copy the template code
+ //
+ KxUnexpectedInterrupt.DispatchCode[i] = KiInterruptTemplate[i];
+ }
- /* Initialize portable parts of the OS */
+ //
+ // Set DMA coherency
+ //
+ KiDmaIoCoherency = 0;
+
+ //
+ // Sweep D-Cache
+ //
+ 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);
+
+ //
+ // Set IRQL and prcessor member/number
+ //
+ Pcr->CurrentIrql = APC_LEVEL;
+ Pcr->SetMember = 1 << Number;
+ Pcr->NotMember = -Pcr->SetMember;
+ Pcr->Number = Number;
+
+ //
+ // Remember our parent
+ //
+ InitThread->ApcState.Process = InitProcess;
+
+ //
+ // Setup the active processor numbers
+ //
+ KeActiveProcessors |= 1 << Number;
+ KeNumberProcessors = Number + 1;
+
+ //
+ // Check if this is the boot CPU
+ //
+ if (!Number)
+ {
+ //
+ // 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 @@
}
else
{
- /* FIXME */
- DPRINT1("SMP Boot support not yet present\n");
- }
-
- /* Setup the Idle Thread */
+ //
+ // FIXME
+ //
+ DPRINT1("ARM MPCore not supported\n");
+ }
+
+ //
+ // Setup the Idle Thread
+ //
KeInitializeThread(InitProcess,
InitThread,
NULL,
@@ -209,61 +242,68 @@
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
Modified: trunk/reactos/ntoskrnl/ke/arm/stubs_asm.s
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/stubs_asm.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/arm/stubs_asm.s (original)
+++ trunk/reactos/ntoskrnl/ke/arm/stubs_asm.s Wed Feb 13 01:50:54 2008
@@ -62,6 +62,9 @@
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 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 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
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?r…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Wed Feb 13 01:50:54 2008
@@ -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>