From e66a86c8b92a912f88e30e80e1b167faed01de58 Mon Sep 17 00:00:00 2001 From: ReactOS Portable Systems Group Date: Sat, 14 Jun 2008 22:02:50 +0000 Subject: [PATCH] - Fix stupid IRQL/Interrupt handling code that someone wrote ;): - Get rid of KeSwapIrql -- both lower and higher IRQL handling was treated the same! - We can now re-activate the assert in the IRQL code - Disable interrupts before changing the interrupt mask!!! - And re-enable them solely if they were enabled. - Clear interrupts mask before setting a new one -- raising isn't always additive! - Fix KiInterruptHandler to perform operations in the right order. - Finish implementing interrupt exit code. - Code KeArmStatusRegisterGet to read CPSR and interrupt status. - Make debug prints a lot more readable and dont trying to acquire the stack during pool allocations. - Setup the clock interval timer!!! - This code regresses progress but makes stuf fwork right. We'll get better after implementing the stall interrupt. svn path=/trunk/; revision=33967 --- reactos/hal/hal/hal_arm.def | 1 - reactos/hal/halarm/generic/hal.c | 66 ++++++++++---- reactos/include/reactos/armddk.h | 11 ++- .../ntoskrnl/include/internal/arm/intrin_i.h | 8 ++ reactos/ntoskrnl/include/internal/arm/ke.h | 25 ++++++ reactos/ntoskrnl/ke/arm/kiinit.c | 4 +- reactos/ntoskrnl/ke/arm/trap.s | 26 +++++- reactos/ntoskrnl/ke/arm/trapc.c | 85 +++++++------------ reactos/ntoskrnl/mm/arm/stubs.c | 18 +--- reactos/ntoskrnl/mm/ppool.c | 5 ++ 10 files changed, 159 insertions(+), 90 deletions(-) diff --git a/reactos/hal/hal/hal_arm.def b/reactos/hal/hal/hal_arm.def index 343bb68829e..33020ec4dff 100644 --- a/reactos/hal/hal/hal_arm.def +++ b/reactos/hal/hal/hal_arm.def @@ -81,7 +81,6 @@ KdComPortInUse=_KdComPortInUse DATA KeFlushWriteBuffer KeGetCurrentIrql KeLowerIrql -KeSwapIrql KeQueryPerformanceCounter KeRaiseIrql KeRaiseIrqlToDpcLevel diff --git a/reactos/hal/halarm/generic/hal.c b/reactos/hal/halarm/generic/hal.c index ff0d2de9cc1..d95d2683516 100644 --- a/reactos/hal/halarm/generic/hal.c +++ b/reactos/hal/halarm/generic/hal.c @@ -393,7 +393,6 @@ HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock) } } - // // INTs on the Versatile: // @@ -491,6 +490,14 @@ UCHAR HalpMaskTable[HIGH_LEVEL + 1] = #define VICSOFTINT (PVOID)0xE0040018 #define VICSOFTINTCLEAR (PVOID)0xE004001C +#define TIMER_LOAD (PVOID)0xE00E2000 +#define TIMER_VALUE (PVOID)0xE00E2004 +#define TIMER_CONTROL (PVOID)0xE00E2008 +#define TIMER_INT_CLEAR (PVOID)0xE00E200C +#define TIMER_INT_STATUS (PVOID)0xE00E2010 +#define TIMER_INT_MASK (PVOID)0xE00E2014 +#define TIMER_BACKGROUND_LOAD (PVOID)0xE00E2018 + #define _clz(a) \ ({ ULONG __value, __arg = (a); \ @@ -513,6 +520,11 @@ VOID HalpStallInterrupt(VOID) { DPRINT1("STALL INTERRUPT!!!\n"); + + // + // Clear the interrupt + // + WRITE_REGISTER_ULONG(TIMER_INT_CLEAR, 1); while (TRUE); } @@ -520,20 +532,39 @@ VOID HalpInitializeInterrupts(VOID) { PKPCR Pcr = (PKPCR)KeGetPcr(); + ULONG ClockInterval; // // Fill out the IRQL mappings // 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 // Pcr->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt; // Pcr->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt; + + // + // Configure the interval to 10ms + // (INTERVAL (10ms) * TIMCLKfreq (1MHz)) + // --------------------------------------- == 10^4 + // (TIMCLKENXdiv (1) * PRESCALEdiv (1)) + // + ClockInterval = 0x2710; + + // + // Enable the timer + // + WRITE_REGISTER_ULONG(TIMER_LOAD, ClockInterval); + WRITE_REGISTER_ULONG(TIMER_CONTROL, + 0 << 0 | // wrapping mode + 1 << 1 | // 32-bit mode + 0 << 2 | // 0 stages of prescale, divided by 1 + 1 << 5 | // enable interrupt + 1 << 6 | // periodic mode + 1 << 7); // enable it } ULONG HalpCurrentTimeIncrement, HalpNextTimeIncrement, HalpNextIntervalCount; @@ -1068,11 +1099,14 @@ FASTCALL KfLowerIrql(IN KIRQL NewIrql) { ULONG InterruptMask; + ARM_STATUS_REGISTER Flags; PKPCR Pcr = (PKPCR)KeGetPcr(); // // Validate the new IRQL // + Flags = KeArmStatusRegisterGet(); + _disable(); ASSERT(NewIrql <= Pcr->CurrentIrql); // @@ -1084,7 +1118,7 @@ KfLowerIrql(IN KIRQL NewIrql) // Setup the interrupt mask for this IRQL // InterruptMask = KeGetPcr()->IrqlTable[NewIrql]; - DPRINT1("New IRQL: %d InterruptMask: %lx\n", NewIrql, InterruptMask); + DPRINT1("[LOWER] IRQL: %d InterruptMask: %lx\n", NewIrql, InterruptMask); // // Clear interrupts associated to the old IRQL @@ -1101,6 +1135,7 @@ KfLowerIrql(IN KIRQL NewIrql) // Save the new IRQL // Pcr->CurrentIrql = NewIrql; + if (!Flags.IrqDisable) _enable(); } KIRQL @@ -1109,11 +1144,14 @@ KfRaiseIrql(IN KIRQL NewIrql) { KIRQL OldIrql; ULONG InterruptMask; + ARM_STATUS_REGISTER Flags; PKPCR Pcr = (PKPCR)KeGetPcr(); // // Save the current IRQL // + Flags = KeArmStatusRegisterGet(); + _disable(); OldIrql = Pcr->CurrentIrql; // @@ -1125,8 +1163,13 @@ KfRaiseIrql(IN KIRQL NewIrql) // Setup the interrupt mask for this IRQL // InterruptMask = KeGetPcr()->IrqlTable[NewIrql]; - DPRINT1("New IRQL: %d InterruptMask: %lx\n", NewIrql, InterruptMask); - //ASSERT(NewIrql >= OldIrql); + DPRINT1("[RAISE] IRQL: %d InterruptMask: %lx\n", NewIrql, InterruptMask); + ASSERT(NewIrql >= OldIrql); + + // + // Clear interrupts associated to the old IRQL + // + WRITE_REGISTER_ULONG(VICINTENCLEAR, 0xFFFFFFFF); // // Set the new interrupt mask @@ -1138,6 +1181,7 @@ KfRaiseIrql(IN KIRQL NewIrql) // Save the new IRQL // Pcr->CurrentIrql = NewIrql; + if (!Flags.IrqDisable) _enable(); return OldIrql; } @@ -1267,15 +1311,6 @@ WRITE_PORT_USHORT( UNIMPLEMENTED; } -KIRQL -KeSwapIrql(IN KIRQL Irql) -{ - // - // Call the generic routine - // - return KfRaiseIrql(Irql); -} - KIRQL KeRaiseIrqlToDpcLevel(VOID) { @@ -1318,7 +1353,6 @@ HalpIdentifyProcessor(VOID) HalpTestCleanSupported = (IdRegister.Architecture == 6); } - VOID HalSweepDcache(VOID) { diff --git a/reactos/include/reactos/armddk.h b/reactos/include/reactos/armddk.h index 94334a91333..ad06607deb4 100644 --- a/reactos/include/reactos/armddk.h +++ b/reactos/include/reactos/armddk.h @@ -128,7 +128,12 @@ struct _TEB* NtCurrentTeb(VOID) // IRQL Support on ARM is similar to MIPS/ALPHA // KIRQL -KeSwapIrql( +KfRaiseIrql( + IN KIRQL NewIrql +); + +VOID +KfLowerIrql( IN KIRQL NewIrql ); @@ -142,8 +147,8 @@ KeRaiseIrqlToDpcLevel( VOID ); -#define KeLowerIrql(NewIrql) KeSwapIrql(NewIrql) -#define KeRaiseIrql(NewIrql, OldIrql) *(OldIrql) = KeSwapIrql(NewIrql) +#define KeLowerIrql(NewIrql) KfLowerIrql(NewIrql) +#define KeRaiseIrql(NewIrql, OldIrql) *(OldIrql) = KfRaiseIrql(NewIrql) // // Cache clean and flush diff --git a/reactos/ntoskrnl/include/internal/arm/intrin_i.h b/reactos/ntoskrnl/include/internal/arm/intrin_i.h index 8c51e148fea..873d6a96fba 100644 --- a/reactos/ntoskrnl/include/internal/arm/intrin_i.h +++ b/reactos/ntoskrnl/include/internal/arm/intrin_i.h @@ -74,6 +74,14 @@ KeArmCacheRegisterGet(VOID) return Value; } +FORCEINLINE +ARM_STATUS_REGISTER +KeArmStatusRegisterGet(VOID) +{ + ARM_STATUS_REGISTER Value; + __asm__ __volatile__ ("mrs %0, cpsr" : "=r"(Value.AsUlong) : : "cc"); + return Value; +} FORCEINLINE VOID diff --git a/reactos/ntoskrnl/include/internal/arm/ke.h b/reactos/ntoskrnl/include/internal/arm/ke.h index dc546513f7f..ff7f340e3a4 100644 --- a/reactos/ntoskrnl/include/internal/arm/ke.h +++ b/reactos/ntoskrnl/include/internal/arm/ke.h @@ -24,6 +24,31 @@ typedef union _ARM_TTB_REGISTER ULONG AsUlong; } ARM_TTB_REGISTER; +typedef union _ARM_STATUS_REGISTER +{ + + struct + { + ULONG Mode:5; + ULONG State:1; + ULONG FiqDisable:1; + ULONG IrqDisable:1; + ULONG ImpreciseAbort:1; + ULONG Endianness:1; + ULONG Sbz:6; + ULONG GreaterEqual:4; + ULONG Sbz1:4; + ULONG Java:1; + ULONG Sbz2:2; + ULONG StickyOverflow:1; + ULONG Overflow:1; + ULONG CarryBorrowExtend:1; + ULONG Zero:1; + ULONG NegativeLessThan:1; + }; + ULONG AsUlong; +} ARM_STATUS_REGISTER; + typedef union _ARM_DOMAIN_REGISTER { struct diff --git a/reactos/ntoskrnl/ke/arm/kiinit.c b/reactos/ntoskrnl/ke/arm/kiinit.c index 8c5c1e71010..8ee7be0b6c6 100644 --- a/reactos/ntoskrnl/ke/arm/kiinit.c +++ b/reactos/ntoskrnl/ke/arm/kiinit.c @@ -273,7 +273,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess, // // Raise to Dispatch // - KeSwapIrql(DISPATCH_LEVEL); + KfRaiseIrql(DISPATCH_LEVEL); // // Set the Idle Priority to 0. This will jump into Phase 1 @@ -290,7 +290,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess, // // Raise back to HIGH_LEVEL // - KeSwapIrql(HIGH_LEVEL); + KfRaiseIrql(HIGH_LEVEL); } VOID diff --git a/reactos/ntoskrnl/ke/arm/trap.s b/reactos/ntoskrnl/ke/arm/trap.s index 6b8b3a88de1..b282d662080 100644 --- a/reactos/ntoskrnl/ke/arm/trap.s +++ b/reactos/ntoskrnl/ke/arm/trap.s @@ -323,10 +323,32 @@ AbortExit: IntExit: // - // FIXME: TODO + // Skip IRQL // - b . + add sp, sp, #(4) + + // + // Get the SPSR and restore it + // + ldr r0, [sp], #4 + msr spsr_all, r0 + // + // Restore the registers + // + ldmia sp, {r0-r14}^ + mov r0, r0 + + // + // Advance in the trap frame + // + add sp, sp, #(4*15) + + // + // Restore program execution state + // + ldmia sp, {sp, lr, pc}^ + b . ENTRY_END KiInterruptException NESTED_ENTRY KiFastInterruptException diff --git a/reactos/ntoskrnl/ke/arm/trapc.c b/reactos/ntoskrnl/ke/arm/trapc.c index fd280bdbfc1..2c061506ffa 100644 --- a/reactos/ntoskrnl/ke/arm/trapc.c +++ b/reactos/ntoskrnl/ke/arm/trapc.c @@ -199,9 +199,7 @@ KiDispatchInterrupt(VOID) // Check if we have a thread to swap to // if (Pcr->Prcb->NextThread) - { - DPRINT1("Switching threads!\n"); - + { // // Next is now current // @@ -219,7 +217,6 @@ KiDispatchInterrupt(VOID) // // Make the old thread ready // - DPRINT1("Queueing the ready thread\n"); KxQueueReadyThread(OldThread, Pcr->Prcb); // @@ -241,6 +238,12 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame, KIRQL OldIrql, Irql; ULONG InterruptCause, InterruptMask; PKPCR Pcr; + + // + // Increment interrupt count + // + Pcr = (PKPCR)KeGetPcr(); + Pcr->Prcb->InterruptCount++; // // Get the old IRQL @@ -252,62 +255,49 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame, // Get the interrupt source // InterruptCause = HalGetInterruptSource(); - DPRINT1("Interrupt (%x) @ %p %p\n", InterruptCause, TrapFrame->SvcLr, TrapFrame->Pc); - DPRINT1("OLD IRQL: %x\n", OldIrql); + DPRINT1("[INT] (%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 + // Raise to the new IRQL // - if (OldIrql < Irql) - { - // - // We should just return, probably - // - DPRINT1("IRQL Race!\n"); - while (TRUE); - } - + KfRaiseIrql(Irql); + // // Check if this interrupt is at DISPATCH or higher // if (Irql > DISPATCH_LEVEL) + { + // + // FIXME: Switch to interrupt stack + // + DPRINT1("[ISR]\n"); + } + else { // - // ISR Handling Code + // We know this is APC or DPC. // - DPRINT1("ISR!\n"); - while (TRUE); + DPRINT1("[DPC/APC]\n"); + HalClearSoftwareInterrupt(Irql); } - - // - // 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); + DPRINT1("[ISR RETURN]\n"); + + // + // Re-enable interrupts and return IRQL + // + KeLowerIrql(OldIrql); + _enable(); } NTSTATUS @@ -315,8 +305,8 @@ KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame) { NTSTATUS Status; PVOID Address = (PVOID)KeArmFaultAddressRegisterGet(); - DPRINT1("Data Abort (%x) @ %p %p\n", Address, TrapFrame->SvcLr, TrapFrame->Pc); - DPRINT1("Abort Reason: %d\n", KeArmFaultStatusRegisterGet()); + DPRINT1("[ABORT] (%x) @ %p/%p/%p\n", + KeArmFaultStatusRegisterGet(), Address, TrapFrame->SvcLr, TrapFrame->Pc); // // Check if this is a page fault @@ -327,10 +317,10 @@ KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame) Address, KernelMode, TrapFrame); - DPRINT1("Status: %x\n", Status); if (Status == STATUS_SUCCESS) return Status; } + UNIMPLEMENTED; while (TRUE); return STATUS_SUCCESS; } @@ -358,7 +348,7 @@ KiSystemService(IN PKTHREAD Thread, // Get the system call ID // Id = Instruction & 0xFFFFF; - DPRINT1("System call (%X) from thread: %p (%d) \n", Id, Thread, Thread->PreviousMode); + DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode); // // Get the descriptor table @@ -367,7 +357,6 @@ KiSystemService(IN PKTHREAD Thread, Offset = ((Id >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK); ServiceTable += Offset; DescriptorTable = (PVOID)ServiceTable; - DPRINT1("Descriptor Table: %p (Count %d)\n", DescriptorTable, DescriptorTable->Limit); // // Get the service call number and validate it @@ -386,8 +375,6 @@ KiSystemService(IN PKTHREAD Thread, // Save the function responsible for handling this system call // SystemCall = (PVOID)DescriptorTable->Base[Number]; - DPRINT1("Handler: %p\n", SystemCall); - DPRINT1("NtClose: %p\n", NtClose); // // Check if this is a GUI call @@ -404,10 +391,8 @@ KiSystemService(IN PKTHREAD Thread, // // Check how many arguments this system call takes // - DPRINT1("Number: %d\n", Number); ArgumentCount = DescriptorTable->Number[Number] / 4; ASSERT(ArgumentCount <= 20); - DPRINT1("Argument Count: %d\n", ArgumentCount); // // Copy the register-arguments first @@ -421,7 +406,6 @@ KiSystemService(IN PKTHREAD Thread, // Arguments[i] = *Argument; Argument++; - DPRINT1("Argument %d: %x\n", i, Arguments[i]); } // @@ -432,7 +416,6 @@ KiSystemService(IN PKTHREAD Thread, // // FIXME: Validate the user stack // - DPRINT1("User stack: %p\n", TrapFrame->UserSp); // // Copy the rest @@ -445,7 +428,6 @@ KiSystemService(IN PKTHREAD Thread, // Arguments[i] = *Argument; Argument++; - DPRINT1("Argument %d: %x\n", i, Arguments[i]); } } @@ -461,7 +443,6 @@ KiSoftwareInterruptHandler(IN PKTRAP_FRAME TrapFrame) PKTHREAD Thread; KPROCESSOR_MODE PreviousMode; ULONG Instruction; - DPRINT1("SWI @ %p %p \n", TrapFrame->Pc, TrapFrame->UserLr); // // Get the current thread diff --git a/reactos/ntoskrnl/mm/arm/stubs.c b/reactos/ntoskrnl/mm/arm/stubs.c index 4d2f9e48957..7d971637dc0 100644 --- a/reactos/ntoskrnl/mm/arm/stubs.c +++ b/reactos/ntoskrnl/mm/arm/stubs.c @@ -350,8 +350,7 @@ MmCreateVirtualMappingForKernel(IN PVOID Address, MMPTE TempPte, TempPde; NTSTATUS Status; PFN_NUMBER Pfn; - DPRINT1("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n", - Address, Protection, *Pages, PageCount); + DPRINT1("[KMAP]: %p %d\n", Address, PageCount); ASSERT(Address >= MmSystemRangeStart); // @@ -466,9 +465,6 @@ MmCreateVirtualMappingUnsafe(IN PEPROCESS Process, IN PPFN_TYPE Pages, IN ULONG PageCount) { - DPRINT1("MmCreateVirtualMappingUnsafe(%p %x, %x, %x, %d)\n", - Process, Address, Protection, *Pages, PageCount); - // // Are we only handling the kernel? // @@ -499,9 +495,7 @@ MmCreateVirtualMapping(IN PEPROCESS Process, IN ULONG PageCount) { ULONG i; - DPRINT1("MmCreateVirtualMapping(%p %x, %x, %x, %d)\n", - Process, Address, Protection, *Pages, PageCount); - + // // Loop each page // @@ -556,7 +550,6 @@ MmGetPhysicalAddress(IN PVOID Address) { PHYSICAL_ADDRESS PhysicalAddress = {{0}}; PMMPTE PointerPte; - DPRINT1("MmGetPhysicalAddress(%lx)\n", Address); // // Early boot PCR check @@ -570,7 +563,6 @@ MmGetPhysicalAddress(IN PVOID Address) ASSERT(PointerPte->u.Hard.L1.Section.Type == SectionPte); PhysicalAddress.QuadPart = PointerPte->u.Hard.L1.Section.BaseAddress; PhysicalAddress.QuadPart <<= CPT_SHIFT; - DPRINT1("Base: %p\n", PhysicalAddress.LowPart); PhysicalAddress.LowPart += BYTE_OFFSET(Address); return PhysicalAddress; } @@ -605,7 +597,6 @@ MmCreateHyperspaceMapping(IN PFN_TYPE Page) PMMPTE PointerPte, FirstPte, LastPte; MMPTE TempPte; PVOID Address; - DPRINT1("MmCreateHyperspaceMapping(%lx)\n", Page); // // Loop hyperspace PTEs (1MB) @@ -650,7 +641,7 @@ MmCreateHyperspaceMapping(IN PFN_TYPE Page) // Address = HYPER_SPACE + ((PointerPte - FirstPte) * PAGE_SIZE); KiFlushSingleTb(FALSE, Address); - DPRINT1("MmCreateHyperspaceMapping(%lx)\n", Address); + DPRINT1("[HMAP]: %p %lx\n", Address, Page); return Address; } @@ -660,7 +651,7 @@ MmDeleteHyperspaceMapping(IN PVOID Address) { PFN_TYPE Pfn; PMMPTE PointerPte; - DPRINT1("MmDeleteHyperspaceMapping(%lx)\n", Address); + DPRINT1("[HUNMAP]: %p\n", Address); // // Get the PTE @@ -740,7 +731,6 @@ MiInitPageDirectoryMap(VOID) PHYSICAL_ADDRESS BoundaryAddressMultiple; PVOID BaseAddress; NTSTATUS Status; - DPRINT1("MiInitPageDirectoryMap()\n"); // // Create memory area for the PTE area diff --git a/reactos/ntoskrnl/mm/ppool.c b/reactos/ntoskrnl/mm/ppool.c index a4c4f2ed430..b2cc217fcf7 100644 --- a/reactos/ntoskrnl/mm/ppool.c +++ b/reactos/ntoskrnl/mm/ppool.c @@ -29,7 +29,12 @@ #define R_PRINT_ADDRESS(addr) KeRosPrintAddress(addr) #define R_PANIC() KeBugCheck(0) #define R_DEBUG DbgPrint + +#ifdef _ARM_ +#define R_GET_STACK_FRAMES(ptr,cnt) +#else #define R_GET_STACK_FRAMES(ptr,cnt) RtlWalkFrameChain((PVOID*)ptr,cnt, 0) +#endif #include "rpoolmgr.h"