Author: ros-arm-bringup Date: Sat Jun 14 17:02:50 2008 New Revision: 33967
URL: http://svn.reactos.org/svn/reactos?rev=33967&view=rev Log: - 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.
Modified: trunk/reactos/hal/hal/hal_arm.def trunk/reactos/hal/halarm/generic/hal.c trunk/reactos/include/reactos/armddk.h trunk/reactos/ntoskrnl/include/internal/arm/intrin_i.h trunk/reactos/ntoskrnl/include/internal/arm/ke.h trunk/reactos/ntoskrnl/ke/arm/kiinit.c trunk/reactos/ntoskrnl/ke/arm/trap.s trunk/reactos/ntoskrnl/ke/arm/trapc.c trunk/reactos/ntoskrnl/mm/arm/stubs.c trunk/reactos/ntoskrnl/mm/ppool.c
Modified: trunk/reactos/hal/hal/hal_arm.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/hal/hal_arm.def?rev=339... ============================================================================== --- trunk/reactos/hal/hal/hal_arm.def [iso-8859-1] (original) +++ trunk/reactos/hal/hal/hal_arm.def [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -81,7 +81,6 @@ KeFlushWriteBuffer KeGetCurrentIrql KeLowerIrql -KeSwapIrql KeQueryPerformanceCounter KeRaiseIrql KeRaiseIrqlToDpcLevel
Modified: trunk/reactos/hal/halarm/generic/hal.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halarm/generic/hal.c?re... ============================================================================== --- trunk/reactos/hal/halarm/generic/hal.c [iso-8859-1] (original) +++ trunk/reactos/hal/halarm/generic/hal.c [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -392,7 +392,6 @@ if (strstr(CommandLine, "BREAK")) DbgBreakPoint(); } } -
// // INTs on the Versatile: @@ -491,6 +490,14 @@ #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 @@ HalpStallInterrupt(VOID) { DPRINT1("STALL INTERRUPT!!!\n"); + + // + // Clear the interrupt + // + WRITE_REGISTER_ULONG(TIMER_INT_CLEAR, 1); while (TRUE); }
@@ -520,20 +532,39 @@ 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 @@ 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 @@ // 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 @@ // Save the new IRQL // Pcr->CurrentIrql = NewIrql; + if (!Flags.IrqDisable) _enable(); }
KIRQL @@ -1109,11 +1144,14 @@ { 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 @@ // 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 @@ // Save the new IRQL // Pcr->CurrentIrql = NewIrql; + if (!Flags.IrqDisable) _enable(); return OldIrql; }
@@ -1268,15 +1312,6 @@ }
KIRQL -KeSwapIrql(IN KIRQL Irql) -{ - // - // Call the generic routine - // - return KfRaiseIrql(Irql); -} - -KIRQL KeRaiseIrqlToDpcLevel(VOID) { // @@ -1317,7 +1352,6 @@ // HalpTestCleanSupported = (IdRegister.Architecture == 6); } -
VOID HalSweepDcache(VOID)
Modified: trunk/reactos/include/reactos/armddk.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/armddk.h?re... ============================================================================== --- trunk/reactos/include/reactos/armddk.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/armddk.h [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -128,7 +128,12 @@ // IRQL Support on ARM is similar to MIPS/ALPHA // KIRQL -KeSwapIrql( +KfRaiseIrql( + IN KIRQL NewIrql +); + +VOID +KfLowerIrql( IN KIRQL NewIrql );
@@ -142,8 +147,8 @@ 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
Modified: trunk/reactos/ntoskrnl/include/internal/arm/intrin_i.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/a... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/arm/intrin_i.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/arm/intrin_i.h [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -74,6 +74,14 @@ 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
Modified: trunk/reactos/ntoskrnl/include/internal/arm/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/a... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/arm/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/arm/ke.h [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -23,6 +23,31 @@ }; 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 {
Modified: trunk/reactos/ntoskrnl/ke/arm/kiinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/kiinit.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/ke/arm/kiinit.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/arm/kiinit.c [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -273,7 +273,7 @@ // // 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 @@ // // Raise back to HIGH_LEVEL // - KeSwapIrql(HIGH_LEVEL); + KfRaiseIrql(HIGH_LEVEL); }
VOID
Modified: trunk/reactos/ntoskrnl/ke/arm/trap.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/trap.s?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/arm/trap.s [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/arm/trap.s [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -323,10 +323,32 @@ IntExit:
// - // FIXME: TODO - // - b . - + // Skip IRQL + // + 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
Modified: trunk/reactos/ntoskrnl/ke/arm/trapc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/trapc.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/arm/trapc.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/arm/trapc.c [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -199,9 +199,7 @@ // 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 @@ // // Make the old thread ready // - DPRINT1("Queueing the ready thread\n"); KxQueueReadyThread(OldThread, Pcr->Prcb);
// @@ -241,6 +238,12 @@ 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 @@ // 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 - // - if (OldIrql < Irql) - { - // - // We should just return, probably - // - DPRINT1("IRQL Race!\n"); - while (TRUE); - } - + + // + // Raise to the new IRQL + // + KfRaiseIrql(Irql); + // // 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); + { + // + // FIXME: Switch to interrupt stack + // + DPRINT1("[ISR]\n"); + } + else + { + // + // We know this is APC or DPC. + // + DPRINT1("[DPC/APC]\n"); + HalClearSoftwareInterrupt(Irql); + } + + // + // Call the registered interrupt routine + // + Pcr->InterruptRoutine[Irql](); + DPRINT1("[ISR RETURN]\n"); + + // + // Re-enable interrupts and return IRQL + // + KeLowerIrql(OldIrql); _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 @@ -315,8 +305,8 @@ { 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 @@ Address, KernelMode, TrapFrame); - DPRINT1("Status: %x\n", Status); if (Status == STATUS_SUCCESS) return Status; }
+ UNIMPLEMENTED; while (TRUE); return STATUS_SUCCESS; } @@ -358,7 +348,7 @@ // 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 @@ 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 @@ // 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 @@ // // 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 @@ // Arguments[i] = *Argument; Argument++; - DPRINT1("Argument %d: %x\n", i, Arguments[i]); }
// @@ -432,7 +416,6 @@ // // FIXME: Validate the user stack // - DPRINT1("User stack: %p\n", TrapFrame->UserSp);
// // Copy the rest @@ -445,7 +428,6 @@ // Arguments[i] = *Argument; Argument++; - DPRINT1("Argument %d: %x\n", i, Arguments[i]); } }
@@ -461,7 +443,6 @@ PKTHREAD Thread; KPROCESSOR_MODE PreviousMode; ULONG Instruction; - DPRINT1("SWI @ %p %p \n", TrapFrame->Pc, TrapFrame->UserLr);
// // Get the current thread
Modified: trunk/reactos/ntoskrnl/mm/arm/stubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/arm/stubs.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/mm/arm/stubs.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/arm/stubs.c [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -350,8 +350,7 @@ 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 @@ 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 @@ 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 @@ { PHYSICAL_ADDRESS PhysicalAddress = {{0}}; PMMPTE PointerPte; - DPRINT1("MmGetPhysicalAddress(%lx)\n", Address);
// // Early boot PCR check @@ -570,7 +563,6 @@ 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 @@ PMMPTE PointerPte, FirstPte, LastPte; MMPTE TempPte; PVOID Address; - DPRINT1("MmCreateHyperspaceMapping(%lx)\n", Page);
// // Loop hyperspace PTEs (1MB) @@ -650,7 +641,7 @@ // 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 @@ { PFN_TYPE Pfn; PMMPTE PointerPte; - DPRINT1("MmDeleteHyperspaceMapping(%lx)\n", Address); + DPRINT1("[HUNMAP]: %p\n", Address);
// // Get the PTE @@ -740,7 +731,6 @@ PHYSICAL_ADDRESS BoundaryAddressMultiple; PVOID BaseAddress; NTSTATUS Status; - DPRINT1("MiInitPageDirectoryMap()\n");
// // Create memory area for the PTE area
Modified: trunk/reactos/ntoskrnl/mm/ppool.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ppool.c?rev=339... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ppool.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ppool.c [iso-8859-1] Sat Jun 14 17:02:50 2008 @@ -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"