- 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
This commit is contained in:
ReactOS Portable Systems Group 2008-06-14 22:02:50 +00:00
parent ff164b383d
commit e66a86c8b9
10 changed files with 159 additions and 90 deletions

View file

@ -81,7 +81,6 @@ KdComPortInUse=_KdComPortInUse DATA
KeFlushWriteBuffer
KeGetCurrentIrql
KeLowerIrql
KeSwapIrql
KeQueryPerformanceCounter
KeRaiseIrql
KeRaiseIrqlToDpcLevel

View file

@ -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)
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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"