- 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
This commit is contained in:
ReactOS Portable Systems Group 2008-06-11 16:48:07 +00:00
parent 1f2f57762a
commit e6d9765059
13 changed files with 421 additions and 27 deletions

View file

@ -42,6 +42,7 @@ HalGetAdapter
HalGetBusData
HalGetBusDataByOffset
HalGetEnvironmentVariable
HalGetInterruptSource
HalGetInterruptVector
HalHandleNMI
HalInitSystem

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -142,7 +142,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
//
// Point to the same template
//
Pcr->InterruptRoutine[i] = &KxUnexpectedInterrupt.DispatchCode;
Pcr->InterruptRoutine[i] = (PVOID)&KxUnexpectedInterrupt.DispatchCode;
}
//

View file

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

View file

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

View file

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

View file

@ -403,6 +403,11 @@
<file>psctx.c</file>
</directory>
</if>
<if property="ARCH" value="arm">
<directory name="arm">
<file>psctx.c</file>
</directory>
</if>
<file>debug.c</file>
<file>job.c</file>
<file>kill.c</file>

View file

@ -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 <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* 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 */