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.

svn path=/trunk/; revision=32334
This commit is contained in:
ReactOS Portable Systems Group 2008-02-12 22:50:54 +00:00
parent 93970a965e
commit ed323f3711
8 changed files with 362 additions and 154 deletions

View 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;

View file

@ -135,6 +135,7 @@ typedef struct _KPRCB
UCHAR NodeColor;
UCHAR Spare1;
ULONG NodeShiftedColor;
ULONG PcrPage;
struct _KNODE *ParentNode;
ULONG MultiThreadProcessorSet;
struct _KPRCB *MultiThreadSetMaster;

View file

@ -22,6 +22,11 @@
#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

View 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

View file

@ -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();
}

View file

@ -14,14 +14,10 @@
/* GLOBALS ********************************************************************/
KINTERRUPT KxUnexpectedInterrupt;
BOOLEAN KeIsArmV6;
ULONG KeFixedTbEntries;
ULONG KeNumberProcessIds;
ULONG KeNumberTbEntries;
VOID HalSweepDcache(VOID);
VOID HalSweepIcache(VOID);
#define __ARMV6__ KeIsArmV6
//
@ -44,103 +40,6 @@ DebugService(IN ULONG ServiceType,
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
NTAPI
KiInitializeKernel(IN PKPROCESS InitProcess,
@ -151,34 +50,164 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
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);
//
// Initialize the platform
//
HalInitializeProcessor(Number, LoaderBlock);
/* Save CPU state */
KiSaveProcessorControlState(&Prcb->ProcessorState);
/* Initialize spinlocks and DPC data */
//
// 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 @@ 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

View 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

View 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>