From e6d9765059166da0d84ec3d54fac376167ea97b9 Mon Sep 17 00:00:00 2001 From: ReactOS Portable Systems Group Date: Wed, 11 Jun 2008 16:48:07 +0000 Subject: [PATCH] - Fix build on ARM: - _iob is already defined as a dll_import - _rotl intrinsic is now implemented (should use rol instruction, but not sure on the syntax!) - Add a stub psctx.h for ARM - Added InterlockedEXchangePointers - Fix uninitialized variable warning in ex/resource.c - Start to implement interrupt handling: - We now have a rudimentary interrupt handler that takes care of software interrupts - We now have a rudimentary DPC handler which takes care of switching to the next thread, if any - We now setup the HAL Interrupt Source -> IRQL Table (The IRQLMask Table). - Implemented HalGetInterruptSource, which allows us to get the interrupt # that cause the IRQ. Note: this wasn't needed on Alpha/PPC/MIPS NT ports, because that information is stored on the CPU, and the kernel could read it -- we must abstract it through the HAL. - Add the OldIrql to the TRAP_FRAME, we don't use it yet. - We are now ready to context switch to the Phase 1 thread. svn path=/trunk/; revision=33933 --- reactos/hal/hal/hal_arm.def | 1 + reactos/hal/halarm/generic/hal.c | 113 +++++++++++++--- reactos/include/ndk/arm/ketypes.h | 4 +- reactos/include/psdk/intrin_arm.h | 14 ++ reactos/include/reactos/armddk.h | 6 +- reactos/lib/sdk/crt/string/scanf.c | 2 +- reactos/ntoskrnl/ex/resource.c | 2 +- reactos/ntoskrnl/ke/arm/kiinit.c | 2 +- reactos/ntoskrnl/ke/arm/stubs_asm.s | 2 +- reactos/ntoskrnl/ke/arm/trap.s | 90 +++++++++++++ reactos/ntoskrnl/ke/arm/trapc.c | 160 +++++++++++++++++++++++ reactos/ntoskrnl/ntoskrnl-generic.rbuild | 5 + reactos/ntoskrnl/ps/arm/psctx.c | 47 +++++++ 13 files changed, 421 insertions(+), 27 deletions(-) create mode 100644 reactos/ntoskrnl/ps/arm/psctx.c diff --git a/reactos/hal/hal/hal_arm.def b/reactos/hal/hal/hal_arm.def index 3eae6a20af2..343bb68829e 100644 --- a/reactos/hal/hal/hal_arm.def +++ b/reactos/hal/hal/hal_arm.def @@ -42,6 +42,7 @@ HalGetAdapter HalGetBusData HalGetBusDataByOffset HalGetEnvironmentVariable +HalGetInterruptSource HalGetInterruptVector HalHandleNMI HalInitSystem diff --git a/reactos/hal/halarm/generic/hal.c b/reactos/hal/halarm/generic/hal.c index 995c2d28d57..ff0d2de9cc1 100644 --- a/reactos/hal/halarm/generic/hal.c +++ b/reactos/hal/halarm/generic/hal.c @@ -414,7 +414,7 @@ HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock) // CLOCK_LEVEL - 0x10 (everything disabled except 4) // POWER_LEVEL, IPI_LEVEL, HIGH_LEVEL - 0x00 (everything disabled) -ULONG HalpIrqlTable[] = +ULONG HalpIrqlTable[HIGH_LEVEL + 1] = { 0xFFFFFFFF, // IRQL 0 PASSIVE_LEVEL 0xFFFFFFFD, // IRQL 1 APC_LEVEL @@ -450,6 +450,64 @@ ULONG HalpIrqlTable[] = 0x00, // IRQL 31 HIGH_LEVEL }; +UCHAR HalpMaskTable[HIGH_LEVEL + 1] = +{ + PROFILE_LEVEL, + APC_LEVEL, + DISPATCH_LEVEL, + IPI_LEVEL, + CLOCK2_LEVEL, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 26, + 26 +}; + +#define VICINTSTATUS (PVOID)0xE0040000 +#define VICINTENABLE (PVOID)0xE0040010 +#define VICINTENCLEAR (PVOID)0xE0040014 +#define VICSOFTINT (PVOID)0xE0040018 +#define VICSOFTINTCLEAR (PVOID)0xE004001C + + +#define _clz(a) \ +({ ULONG __value, __arg = (a); \ + asm ("clz\t%0, %1": "=r" (__value): "r" (__arg)); \ + __value; }) + +ULONG +HalGetInterruptSource(VOID) +{ + ULONG InterruptStatus; + + // + // Get the interrupt status, and return the highest bit set + // + InterruptStatus = READ_REGISTER_ULONG(VICINTSTATUS); + return 31 - _clz(InterruptStatus); +} VOID HalpStallInterrupt(VOID) @@ -461,20 +519,16 @@ HalpStallInterrupt(VOID) VOID HalpInitializeInterrupts(VOID) { - ULONG i; PKPCR Pcr = (PKPCR)KeGetPcr(); // // Fill out the IRQL mappings // - for (i = 0; i < (HIGH_LEVEL + 1); i++) - { - // - // Save the valeue in the PCR - // - Pcr->IrqlTable[i] = HalpIrqlTable[i]; - } - + RtlCopyMemory(Pcr->IrqlTable, HalpIrqlTable, sizeof(Pcr->IrqlTable)); + RtlCopyMemory(Pcr->IrqlMask, HalpMaskTable, sizeof(Pcr->IrqlMask)); +// Pcr->IrqlTable = HalpIrqlTable; + // Pcr->IrqlMask = HalpMaskTable; + // // Setup the clock and profile interrupt // @@ -484,10 +538,6 @@ HalpInitializeInterrupts(VOID) ULONG HalpCurrentTimeIncrement, HalpNextTimeIncrement, HalpNextIntervalCount; -#define VICINTENABLE (PVOID)0xE0040010 -#define VICINTENCLEAR (PVOID)0xE0040014 -#define VICSOFTINT (PVOID)0xE0040018 -#define VICSOFTINTCLEAR (PVOID)0xE004001C /* * @implemented @@ -714,14 +764,39 @@ HalRequestSoftwareInterrupt(IN KIRQL Request) WRITE_REGISTER_ULONG(VICSOFTINT, Interrupt); } -VOID FASTCALL -HalClearSoftwareInterrupt( - IN KIRQL Request) +VOID +FASTCALL +HalClearSoftwareInterrupt(IN KIRQL Request) { - UNIMPLEMENTED; + ULONG Interrupt = 0; + + // + // Get the interrupt that maches this IRQL level + // + switch (Request) + { + case APC_LEVEL: + + Interrupt = 1 << 1; + break; + + case DISPATCH_LEVEL: + + Interrupt = 1 << 2; + break; + + default: + + ASSERT(FALSE); + } + + // + // Force a software interrupt + // + DPRINT1("About to kill interrupt mask: %d\n", Interrupt); + WRITE_REGISTER_ULONG(VICSOFTINTCLEAR, Interrupt); } - VOID NTAPI HalReturnToFirmware( diff --git a/reactos/include/ndk/arm/ketypes.h b/reactos/include/ndk/arm/ketypes.h index cbb52eed4b9..10486e25b5a 100644 --- a/reactos/include/ndk/arm/ketypes.h +++ b/reactos/include/ndk/arm/ketypes.h @@ -78,8 +78,8 @@ typedef struct _KTRAP_FRAME ULONG SvcSp; ULONG SvcLr; ULONG Pc; -// UCHAR OldIrql; -// UCHAR PreviousMode; + ULONG OldIrql; +// UCHAR PreviousMode; // ULONG Fpscr; // ULONG FpExc; // ULONG S[33]; diff --git a/reactos/include/psdk/intrin_arm.h b/reactos/include/psdk/intrin_arm.h index 43808d2db7e..22395e8872e 100644 --- a/reactos/include/psdk/intrin_arm.h +++ b/reactos/include/psdk/intrin_arm.h @@ -83,6 +83,12 @@ static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volat return a; } + +static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) +{ + return _InterlockedExchange(Target, Value); +} + static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask) { char x; @@ -276,5 +282,13 @@ static __inline__ __attribute__((always_inline)) void _enable(void) ); } +#ifndef __MSVCRT__ +static __inline__ __attribute__((always_inline)) unsigned long _rotl(const unsigned long value, const unsigned char shift) +{ + return (((value) << ((int)(shift))) | ((value) >> (32 - (int)(shift)))); +} +#endif + + #endif /* EOF */ diff --git a/reactos/include/reactos/armddk.h b/reactos/include/reactos/armddk.h index fd51cfc13f5..e562106f697 100644 --- a/reactos/include/reactos/armddk.h +++ b/reactos/include/reactos/armddk.h @@ -53,7 +53,9 @@ typedef struct _KFLOATING_SAVE // On ARM, it's actually readable from user-mode, much like KUSER_SHARED_DATA // #ifdef _WINNT_H -#define PKINTERRUPT_ROUTINE PVOID // Hack! +typedef +VOID +(*PKINTERRUPT_ROUTINE)(VOID); #endif typedef struct _KPCR { @@ -85,7 +87,7 @@ typedef struct _KPCR PVOID InstructionBusError; ULONG CachePolicy; ULONG AlignedCachePolicy; -// UCHAR IrqlMask[64]; + UCHAR IrqlMask[HIGH_LEVEL + 1]; ULONG IrqlTable[HIGH_LEVEL + 1]; UCHAR CurrentIrql; KAFFINITY SetMember; diff --git a/reactos/lib/sdk/crt/string/scanf.c b/reactos/lib/sdk/crt/string/scanf.c index 1612eeb33c4..e0ba480eb67 100644 --- a/reactos/lib/sdk/crt/string/scanf.c +++ b/reactos/lib/sdk/crt/string/scanf.c @@ -33,7 +33,7 @@ #define debugstr_a #endif -extern FILE _iob[]; +//extern FILE _iob[]; /* helper function for *scanf. Returns the value of character c in the * given base, or -1 if the given character is not a digit of the base. diff --git a/reactos/ntoskrnl/ex/resource.c b/reactos/ntoskrnl/ex/resource.c index 25ed81d41f9..ad3e7c516a9 100644 --- a/reactos/ntoskrnl/ex/resource.c +++ b/reactos/ntoskrnl/ex/resource.c @@ -895,7 +895,7 @@ ExAcquireResourceSharedLite(IN PERESOURCE Resource, { KLOCK_QUEUE_HANDLE LockHandle; ERESOURCE_THREAD Thread; - POWNER_ENTRY Owner; + POWNER_ENTRY Owner = NULL; BOOLEAN FirstEntryBusy; /* Get the thread */ diff --git a/reactos/ntoskrnl/ke/arm/kiinit.c b/reactos/ntoskrnl/ke/arm/kiinit.c index e92e4cc01cf..8c5c1e71010 100644 --- a/reactos/ntoskrnl/ke/arm/kiinit.c +++ b/reactos/ntoskrnl/ke/arm/kiinit.c @@ -142,7 +142,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess, // // Point to the same template // - Pcr->InterruptRoutine[i] = &KxUnexpectedInterrupt.DispatchCode; + Pcr->InterruptRoutine[i] = (PVOID)&KxUnexpectedInterrupt.DispatchCode; } // diff --git a/reactos/ntoskrnl/ke/arm/stubs_asm.s b/reactos/ntoskrnl/ke/arm/stubs_asm.s index c5d12e463bf..ea6442f09b7 100644 --- a/reactos/ntoskrnl/ke/arm/stubs_asm.s +++ b/reactos/ntoskrnl/ke/arm/stubs_asm.s @@ -42,7 +42,6 @@ GENERATE_ARM_STUB RtlInitializeContext // // Internal Ke Arch-Specific Helpers // -GENERATE_ARM_STUB KiDispatchInterrupt GENERATE_ARM_STUB KiSaveProcessorControlState GENERATE_ARM_STUB KiInitializeUserApc GENERATE_ARM_STUB KeDisableInterrupts @@ -69,3 +68,4 @@ GENERATE_ARM_STUB DebugService2 GENERATE_ARM_STUB RtlpGetStackLimits GENERATE_ARM_STUB KdpGdbStubInit +GENERATE_ARM_STUB MmDbgTranslatePhysicalAddress diff --git a/reactos/ntoskrnl/ke/arm/trap.s b/reactos/ntoskrnl/ke/arm/trap.s index 77f1322b589..faf2c584d51 100644 --- a/reactos/ntoskrnl/ke/arm/trap.s +++ b/reactos/ntoskrnl/ke/arm/trap.s @@ -141,6 +141,11 @@ // mov r2, sp + // + // Dummy OldIrql + // + //str r0, [sp, #-4]! + // // Save the abort lr // @@ -217,6 +222,91 @@ AbortExit: NESTED_ENTRY KiInterruptException PROLOG_END KiInterruptException + // + // Fixup lr + // + sub lr, lr, #4 + + // + // Save the bottom 4 registers + // + stmdb sp, {r0-r3} + + // + // Save the IRQ lr, sp, spsr, cpsr + // + mov r0, lr + mov r1, sp + mrs r2, cpsr + mrs r3, spsr + + // + // Switch to SVC mode + // + bic r2, r2, #CPSR_MODES + orr r2, r2, #CPSR_SVC_MODE + msr cpsr_c, r2 + + // + // Save the SVC sp before we modify it + // + mov r2, sp + + // + // Dummy OldIrql + // + //str r0, [sp, #-4]! + + // + // Save the IRQ lr + // + str r0, [sp, #-4]! + + // + // Save the SVC lr and sp + // + str lr, [sp, #-4]! + str r2, [sp, #-4]! + + // + // Restore the saved SPSR + // + msr spsr_all, r3 + + // + // Restore our 4 registers + // + ldmdb r1, {r0-r3} + + // + // Make space for the trap frame + // + sub sp, sp, #(4*15) // TrapFrameLength + + // + // Save user-mode registers + // + stmia sp, {r0-r12} + add r0, sp, #(4*13) + stmia r0, {r13-r14}^ + mov r0, r0 + + // + // Save SPSR + // + mrs r0, spsr_all + str r0, [sp, #-4]! + + // + // Call the C handler + // + adr lr, IntExit + mov r0, sp + mov r1, #0 + ldr pc, =KiInterruptHandler + +IntExit: + // // FIXME: TODO // diff --git a/reactos/ntoskrnl/ke/arm/trapc.c b/reactos/ntoskrnl/ke/arm/trapc.c index 3a3f67e4cbb..852d82fd97d 100644 --- a/reactos/ntoskrnl/ke/arm/trapc.c +++ b/reactos/ntoskrnl/ke/arm/trapc.c @@ -28,6 +28,166 @@ KiSystemCall( /* FUNCTIONS ******************************************************************/ +ULONG +HalGetInterruptSource(VOID); + +VOID FASTCALL +HalClearSoftwareInterrupt(IN KIRQL Request); + +VOID +KiDispatchInterrupt(VOID) +{ + PKPCR Pcr; + PKTHREAD NewThread, OldThread; + + // + // Get the PCR and disable interrupts + // + Pcr = (PKPCR)KeGetPcr(); + _disable(); + + // + //Check if we have to deliver DPCs, timers, or deferred threads + // + if ((Pcr->Prcb->DpcData[0].DpcQueueDepth) || + (Pcr->Prcb->TimerRequest) || + (Pcr->Prcb->DeferredReadyListHead.Next)) + { + // + // FIXME: TODO + // + DPRINT1("DPC/Timer Delivery!\n"); + while (TRUE); + } + + // + // Re-enable interrupts + // + _enable(); + + // + // Check for quantum end + // + if (Pcr->Prcb->QuantumEnd) + { + // + // FIXME: TODO + // + DPRINT1("Quantum End!\n"); + while (TRUE); + return; + } + + // + // Check if we have a thread to swap to + // + if (Pcr->Prcb->NextThread) + { + DPRINT1("Switching threads!\n"); + + // + // Next is now current + // + OldThread = Pcr->Prcb->CurrentThread; + NewThread = Pcr->Prcb->NextThread; + Pcr->Prcb->CurrentThread = NewThread; + Pcr->Prcb->NextThread = NULL; + + // + // Update thread states + // + NewThread->State = Running; + OldThread->WaitReason = WrDispatchInt; + + // + // Make the old thread ready + // + DPRINT1("Queueing the ready thread\n"); + KxQueueReadyThread(OldThread, Pcr->Prcb); + + // + // Swap to the new thread + // + DPRINT1("Swapping context!\n"); + //KiSwapContextInternal(); + while (TRUE); + } +} + +VOID +KiInterruptHandler(IN PKTRAP_FRAME TrapFrame, + IN ULONG Reserved) +{ + KIRQL OldIrql, Irql; + ULONG InterruptCause, InterruptMask; + PKPCR Pcr; + + // + // Get the old IRQL + // + OldIrql = TrapFrame->OldIrql; + + // + // Get the interrupt source + // + InterruptCause = HalGetInterruptSource(); + DPRINT1("Interrupt (%x) @ %p %p\n", InterruptCause, TrapFrame->SvcLr, TrapFrame->Pc); + + // + // Get the new IRQL and Interrupt Mask + // + Pcr = (PKPCR)KeGetPcr(); + Irql = Pcr->IrqlMask[InterruptCause]; + InterruptMask = Pcr->IrqlTable[Irql]; + DPRINT1("IRQL (%x) MASK (%x)\n", Irql, InterruptMask); + + // + // Make sure the IRQL is valid + // + //if (OldIrql < Irql) + //{ + // + // We should just return, probably + // + //DPRINT1("IRQL Race!\n"); + //while (TRUE); + //} + + // + // Check if this interrupt is at DISPATCH or higher + // + if (Irql > DISPATCH_LEVEL) + { + // + // ISR Handling Code + // + DPRINT1("ISR!\n"); + while (TRUE); + } + + // + // We know this is APC or DPC. + // Clear the software interrupt. + // Reenable interrupts and update the IRQL + // + HalClearSoftwareInterrupt(Irql); + _enable(); + Pcr->CurrentIrql = Irql; + + // + // Increment interrupt count + // + Pcr->Prcb->InterruptCount++; + + // + // Call the registered interrupt routine + // + DPRINT1("Calling handler\n"); + Pcr->InterruptRoutine[Irql](); + DPRINT1("Done!\n"); + while (TRUE); +} + NTSTATUS KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame) { diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild index 4bd37e0325d..51c35f9c41a 100644 --- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild @@ -403,6 +403,11 @@ psctx.c + + + psctx.c + + debug.c job.c kill.c diff --git a/reactos/ntoskrnl/ps/arm/psctx.c b/reactos/ntoskrnl/ps/arm/psctx.c new file mode 100644 index 00000000000..c23a3d9aa1e --- /dev/null +++ b/reactos/ntoskrnl/ps/arm/psctx.c @@ -0,0 +1,47 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ps/arm/pxctx.c + * PURPOSE: Process Manager: Set/Get Context for ARM + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +PspGetContext(IN PKTRAP_FRAME TrapFrame, + IN PVOID NonVolatileContext, + IN OUT PCONTEXT Context) +{ + PAGED_CODE(); +} + +VOID +NTAPI +PspSetContext(OUT PKTRAP_FRAME TrapFrame, + OUT PVOID NonVolatileContext, + IN PCONTEXT Context, + IN KPROCESSOR_MODE Mode) +{ + PAGED_CODE(); +} + +VOID +NTAPI +PspGetOrSetContextKernelRoutine(IN PKAPC Apc, + IN OUT PKNORMAL_ROUTINE* NormalRoutine, + IN OUT PVOID* NormalContext, + IN OUT PVOID* SystemArgument1, + IN OUT PVOID* SystemArgument2) +{ + UNIMPLEMENTED; +} + +/* EOF */