diff --git a/reactos/hal/halarm/generic/hal.c b/reactos/hal/halarm/generic/hal.c index 925ab3a0f6c..00c87636f82 100644 --- a/reactos/hal/halarm/generic/hal.c +++ b/reactos/hal/halarm/generic/hal.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #define NDEBUG #include @@ -1090,16 +1092,66 @@ KeSwapIrql(IN KIRQL Irql) return 0; } +BOOLEAN HalpProcessorIdentified; +BOOLEAN HalpTestCleanSupported; + +VOID +HalpIdentifyProcessor(VOID) +{ + ARM_ID_CODE_REGISTER IdRegister; + + // + // Don't do it again + // + HalpProcessorIdentified = TRUE; + + // + // Read the ID Code + // + IdRegister = KeArmIdCodeRegisterGet(); + + // + // Architecture "6" CPUs support test-and-clean (926EJ-S and 1026EJ-S) + // + HalpTestCleanSupported = (IdRegister.Architecture == 6); +} + + VOID HalSweepDcache(VOID) { - UNIMPLEMENTED; + // + // We get called very early on, before HalInitSystem or any of the Hal* + // processor routines, so we need to figure out what CPU we're on. + // + if (!HalpProcessorIdentified) HalpIdentifyProcessor(); + + // + // Check if we can do it the ARMv5TE-J way + // + if (HalpTestCleanSupported) + { + // + // Test, clean, flush D-Cache + // + __asm__ __volatile__ ("1: mrc p15, 0, pc, c7, c14, 3; bne 1b"); + } + else + { + // + // We need to do it it by set/way + // + UNIMPLEMENTED; + } } VOID HalSweepIcache(VOID) { - UNIMPLEMENTED; + // + // All ARM cores support the same Icache flush command, no need for HAL work + // + KeArmFlushIcache(); } /* EOF */ diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index d266b313d69..9b1aabff050 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -5368,7 +5368,9 @@ typedef VOID /* ** Architecture specific structures */ - +#define PCR_MINOR_VERSION 1 +#define PCR_MAJOR_VERSION 1 + #ifdef _X86_ typedef ULONG PFN_NUMBER, *PPFN_NUMBER; @@ -5397,9 +5399,6 @@ typedef struct _KPCR_TIB { struct _KPCR_TIB *Self; /* 18 */ } KPCR_TIB, *PKPCR_TIB; /* 1C */ -#define PCR_MINOR_VERSION 1 -#define PCR_MAJOR_VERSION 1 - typedef struct _KPCR { KPCR_TIB Tib; /* 00 */ struct _KPCR *Self; /* 1C */ diff --git a/reactos/ntoskrnl/include/internal/arm/intrin_i.h b/reactos/ntoskrnl/include/internal/arm/intrin_i.h index db3888bf3b5..bc58340bc46 100644 --- a/reactos/ntoskrnl/include/internal/arm/intrin_i.h +++ b/reactos/ntoskrnl/include/internal/arm/intrin_i.h @@ -99,5 +99,12 @@ KeArmInvalidateTlbEntry(IN PVOID Address) __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 1" : : "r"(Address) : "cc"); } +FORCEINLINE +VOID +KeArmFlushIcache(VOID) +{ + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 0" : : "r"(0) : "cc"); +} + #endif diff --git a/reactos/ntoskrnl/ke/arm/kiinit.c b/reactos/ntoskrnl/ke/arm/kiinit.c index b3bd4a38a28..55f9b19ddb1 100644 --- a/reactos/ntoskrnl/ke/arm/kiinit.c +++ b/reactos/ntoskrnl/ke/arm/kiinit.c @@ -141,6 +141,131 @@ KeFlushTb(VOID) KeArmFlushTlb(); } +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); + + /* 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 */ + 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 */ + KiInitSystem(); + + /* Initialize the Idle Process and the Process Listhead */ + InitializeListHead(&KiProcessListHead); + PageDirectory.QuadPart = 0; + KeInitializeProcess(InitProcess, + 0, + 0xFFFFFFFF, + &PageDirectory, + FALSE); + InitProcess->QuantumReset = MAXCHAR; + } + else + { + /* FIXME */ + DPRINT1("SMP Boot support not yet present\n"); + } + + /* Setup the Idle Thread */ + KeInitializeThread(InitProcess, + InitThread, + NULL, + NULL, + NULL, + NULL, + NULL, + IdleStack); + InitThread->NextProcessor = Number; + InitThread->Priority = HIGH_PRIORITY; + InitThread->State = Running; + InitThread->Affinity = 1 << Number; + InitThread->WaitIrql = DISPATCH_LEVEL; + InitProcess->ActiveProcessors = 1 << Number; + + /* HACK for MmUpdatePageDir */ + ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess; + + /* 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 */ + ExpInitializeExecutive(Number, LoaderBlock); + + /* Only do this on the boot CPU */ + if (!Number) + { + /* Calculate the time reciprocal */ + KiTimeIncrementReciprocal = + KiComputeReciprocal(KeMaximumIncrement, + &KiTimeIncrementShiftCount); + + /* 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 */ + KeSwapIrql(DISPATCH_LEVEL); + + /* 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 */ + KiAcquirePrcbLock(Prcb); + if (!Prcb->NextThread) KiIdleSummary |= 1 << Number; + KiReleasePrcbLock(Prcb); + + /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ + KeSwapIrql(HIGH_LEVEL); + LoaderBlock->Prcb = 0; +} + VOID KiInitializeSystem(IN ULONG Magic, IN PLOADER_PARAMETER_BLOCK LoaderBlock) @@ -281,5 +406,54 @@ KiInitializeSystem(IN ULONG Magic, // HalSweepIcache(); HalSweepDcache(); + + // + // Set PCR version + // + Pcr->MinorVersion = PCR_MINOR_VERSION; + Pcr->MajorVersion = PCR_MAJOR_VERSION; + + // + // Set boot PRCB + // + Pcr->Prcb = (PKPRCB)LoaderBlock->Prcb; + + // + // Set the different stacks + // + Pcr->InitialStack = (PVOID)LoaderBlock->KernelStack; + Pcr->PanicStack = (PVOID)LoaderBlock->u.Arm.PanicStack; + Pcr->InterruptStack = (PVOID)LoaderBlock->u.Arm.InterruptStack; + + // + // Set the current thread + // + Pcr->CurrentThread = (PKTHREAD)LoaderBlock->Thread; + + // + // Set the current IRQL to high + // + Pcr->CurrentIrql = HIGH_LEVEL; + + // + // Set processor information + // + Pcr->ProcessorId = KeArmIdCodeRegisterGet().AsUlong; + Pcr->SystemReserved[0] = KeArmControlRegisterGet().AsUlong; + + // + // Initialize the rest of the kernel now + // + KiInitializeKernel((PKPROCESS)LoaderBlock->Process, + (PKTHREAD)LoaderBlock->Thread, + (PVOID)LoaderBlock->KernelStack, + (PKPRCB)LoaderBlock->Prcb, + Pcr->Prcb->Number, + LoaderBlock); + + + // + // Jump to idle loop + // while (TRUE); }