mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
- 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:
parent
1f2f57762a
commit
e6d9765059
13 changed files with 421 additions and 27 deletions
|
@ -42,6 +42,7 @@ HalGetAdapter
|
|||
HalGetBusData
|
||||
HalGetBusDataByOffset
|
||||
HalGetEnvironmentVariable
|
||||
HalGetInterruptSource
|
||||
HalGetInterruptVector
|
||||
HalHandleNMI
|
||||
HalInitSystem
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -142,7 +142,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
//
|
||||
// Point to the same template
|
||||
//
|
||||
Pcr->InterruptRoutine[i] = &KxUnexpectedInterrupt.DispatchCode;
|
||||
Pcr->InterruptRoutine[i] = (PVOID)&KxUnexpectedInterrupt.DispatchCode;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
47
reactos/ntoskrnl/ps/arm/psctx.c
Normal file
47
reactos/ntoskrnl/ps/arm/psctx.c
Normal 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 */
|
Loading…
Reference in a new issue