mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
- Rewrite the low-level trap/exception/system call code from the ground up:
- Do not corrupt the stack anymore - Use a consistent trap frame layout (enable OldIrql and PreviousMode, and set the 0xBADB0D00 debug mark) - Use slower but more correct trap prolog/epilog code for now. - Generalize all prolog/epilog code into macros just like on x86. As a result, traps are now 6 lines of code. - Rewrite the system call interface from the ground up: - System calls didn't actually work: a debug print made the stack layout magical enough so that they didn't normally crush, but only slowly ate the stack. - Copying arguments from caller to system call was, as the comment on the original code so aptly put it, "total shit". - Due to ABI concerns, and to provide an actual template on how you're -supposed- to implement something like system calls on RISC processors, we now use a model similar to BSD, but about ten times better (with that much less code too). We'll document it later on the RosPSG Wiki. - This code probably contains some of the most vile-yet-elegant macro magic ever written for such low-level code as system call dispatching. - The result of all this is that we're at the same place as before (RamdiskAddDevice needs to be implemented by the Ramdisk guys) but with a sane low-level backend that isn't slowly eating away the stack, corrupting data, and basically working through random chance. - Move timebase code from stubs.c to its own file, time.c. - Silence multiple debug prints and fix a corrupted debug print in KiSystemStartup. svn path=/trunk/; revision=34366
This commit is contained in:
parent
8249e5ced9
commit
b513c98fb2
12 changed files with 846 additions and 782 deletions
|
@ -759,7 +759,6 @@ HalRequestSoftwareInterrupt(IN KIRQL Request)
|
|||
//
|
||||
// Force a software interrupt
|
||||
//
|
||||
DPRINT1("[SOFTINT]: %d\n", Request);
|
||||
WRITE_REGISTER_ULONG(VIC_SOFT_INT, 1 << Request);
|
||||
}
|
||||
|
||||
|
@ -768,9 +767,8 @@ FASTCALL
|
|||
HalClearSoftwareInterrupt(IN KIRQL Request)
|
||||
{
|
||||
//
|
||||
// Force a software interrupt
|
||||
// Clear a software interrupt
|
||||
//
|
||||
DPRINT1("[SOFTINTC] %d\n", Request);
|
||||
WRITE_REGISTER_ULONG(VIC_SOFT_INT_CLEAR, 1 << Request);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,13 +59,11 @@ Author:
|
|||
//
|
||||
typedef struct _KTRAP_FRAME
|
||||
{
|
||||
ULONG OldIrql;
|
||||
// UCHAR PreviousMode;
|
||||
// ULONG Fpscr;
|
||||
// ULONG FpExc;
|
||||
// ULONG S[33];
|
||||
// ULONG FpExtra[8];
|
||||
ULONG Spsr;
|
||||
// ULONG FpExtra[8];
|
||||
ULONG DbgArgMark;
|
||||
ULONG R0;
|
||||
ULONG R1;
|
||||
ULONG R2;
|
||||
|
@ -84,6 +82,9 @@ typedef struct _KTRAP_FRAME
|
|||
ULONG SvcSp;
|
||||
ULONG SvcLr;
|
||||
ULONG Pc;
|
||||
ULONG Spsr;
|
||||
ULONG OldIrql;
|
||||
ULONG PreviousMode;
|
||||
} KTRAP_FRAME, *PKTRAP_FRAME;
|
||||
|
||||
#ifndef NTOS_MODE_USER
|
||||
|
|
|
@ -42,8 +42,27 @@
|
|||
/*
|
||||
* Trap Frame offsets
|
||||
*/
|
||||
.equ TrR0, 0x00
|
||||
.equ TrapFrameLength, 0x144
|
||||
.equ TrDbgArgMark, 0x00
|
||||
.equ TrR0, 0x04
|
||||
.equ TrR1, 0x08
|
||||
.equ TrR2, 0x0C
|
||||
.equ TrR3, 0x10
|
||||
.equ TrR4, 0x14
|
||||
.equ TrR5, 0x18
|
||||
.equ TrR6, 0x1C
|
||||
.equ TrR7, 0x20
|
||||
.equ TrR8, 0x24
|
||||
.equ TrR9, 0x28
|
||||
.equ TrR10, 0x2C
|
||||
.equ TrR11, 0x30
|
||||
.equ TrR12, 0x34
|
||||
.equ TrUserSp, 0x38
|
||||
.equ TrUserLr, 0x3C
|
||||
.equ TrSvcSp, 0x40
|
||||
.equ TrSvcLr, 0x44
|
||||
.equ TrPc, 0x48
|
||||
.equ TrSpsr, 0x4C
|
||||
.equ TrapFrameLength, (22 * 0x04)
|
||||
|
||||
/*
|
||||
* PCR
|
||||
|
|
|
@ -19,3 +19,171 @@
|
|||
end_&Name:
|
||||
.endfunc
|
||||
.endm
|
||||
|
||||
.macro TRAP_PROLOG Abort
|
||||
//
|
||||
// Fixup lr
|
||||
//
|
||||
.if \Abort
|
||||
sub lr, lr, #8
|
||||
.else
|
||||
sub lr, lr, #4
|
||||
.endif
|
||||
|
||||
//
|
||||
// Save the bottom 4 registers
|
||||
//
|
||||
stmdb sp, {r0-r3}
|
||||
|
||||
//
|
||||
// Save the abort 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
|
||||
|
||||
//
|
||||
// Make space for the trap frame
|
||||
//
|
||||
sub sp, sp, #TrapFrameLength
|
||||
|
||||
//
|
||||
// Save abt32 state
|
||||
//
|
||||
str r0, [sp, #TrPc]
|
||||
str lr, [sp, #TrSvcLr]
|
||||
str r2, [sp, #TrSvcSp]
|
||||
|
||||
//
|
||||
// Restore the saved SPSR
|
||||
//
|
||||
msr spsr_all, r3
|
||||
|
||||
//
|
||||
// Restore our 4 registers
|
||||
//
|
||||
ldmdb r1, {r0-r3}
|
||||
|
||||
//
|
||||
// Build trap frame
|
||||
// FIXME: Change to stmdb later
|
||||
//
|
||||
str r0, [sp, #TrR0]
|
||||
str r1, [sp, #TrR1]
|
||||
str r2, [sp, #TrR2]
|
||||
str r3, [sp, #TrR3]
|
||||
str r4, [sp, #TrR4]
|
||||
str r5, [sp, #TrR5]
|
||||
str r6, [sp, #TrR6]
|
||||
str r7, [sp, #TrR7]
|
||||
str r8, [sp, #TrR8]
|
||||
str r9, [sp, #TrR9]
|
||||
str r10, [sp, #TrR10]
|
||||
str r11, [sp, #TrR11]
|
||||
str r12, [sp, #TrR12]
|
||||
mov r12, sp
|
||||
add r12, r12, #TrUserSp
|
||||
stm r12, {sp, lr}^
|
||||
mrs r0, spsr_all
|
||||
str r0, [sp, #TrSpsr]
|
||||
ldr r0, =0xBADB0D00
|
||||
str r0, [sp, #TrDbgArgMark]
|
||||
.endm
|
||||
|
||||
.macro SYSCALL_PROLOG
|
||||
//
|
||||
// Make space for the trap frame
|
||||
//
|
||||
sub sp, sp, #TrapFrameLength
|
||||
|
||||
//
|
||||
// Build trap frame
|
||||
// FIXME: Change to stmdb later
|
||||
//
|
||||
str r0, [sp, #TrR0]
|
||||
str r1, [sp, #TrR1]
|
||||
str r2, [sp, #TrR2]
|
||||
str r3, [sp, #TrR3]
|
||||
str r4, [sp, #TrR4]
|
||||
str r5, [sp, #TrR5]
|
||||
str r6, [sp, #TrR6]
|
||||
str r7, [sp, #TrR7]
|
||||
str r8, [sp, #TrR8]
|
||||
str r9, [sp, #TrR9]
|
||||
str r10, [sp, #TrR10]
|
||||
str r11, [sp, #TrR11]
|
||||
str r12, [sp, #TrR12]
|
||||
mov r12, sp
|
||||
add r12, r12, #TrUserSp
|
||||
stm r12, {sp, lr}^
|
||||
str sp, [sp, #TrSvcSp]
|
||||
str lr, [sp, #TrPc]
|
||||
mrs r0, spsr_all
|
||||
str r0, [sp, #TrSpsr]
|
||||
ldr r0, =0xBADB0D00
|
||||
str r0, [sp, #TrDbgArgMark]
|
||||
.endm
|
||||
|
||||
.macro TRAP_EPILOG SystemCall
|
||||
//
|
||||
// ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00)
|
||||
//
|
||||
ldr r0, [sp, #TrDbgArgMark]
|
||||
ldr r1, =0xBADB0D00
|
||||
cmp r0, r1
|
||||
bne 1f
|
||||
|
||||
//
|
||||
// Get the SPSR and restore it
|
||||
//
|
||||
ldr r0, [sp, #TrSpsr]
|
||||
msr spsr_all, r0
|
||||
|
||||
//
|
||||
// Restore the registers
|
||||
// FIXME: Use LDMIA later
|
||||
//
|
||||
mov r0, sp
|
||||
add r0, r0, #TrUserSp
|
||||
ldm r0, {sp, lr}^
|
||||
ldr r0, [sp, #TrR0]
|
||||
ldr r1, [sp, #TrR1]
|
||||
ldr r2, [sp, #TrR2]
|
||||
ldr r3, [sp, #TrR3]
|
||||
ldr r4, [sp, #TrR4]
|
||||
ldr r5, [sp, #TrR5]
|
||||
ldr r6, [sp, #TrR6]
|
||||
ldr r7, [sp, #TrR7]
|
||||
ldr r8, [sp, #TrR8]
|
||||
ldr r9, [sp, #TrR9]
|
||||
ldr r10, [sp, #TrR10]
|
||||
ldr r11, [sp, #TrR11]
|
||||
ldr r12, [sp, #TrR12]
|
||||
|
||||
//
|
||||
// Restore program execution state
|
||||
//
|
||||
.if \SystemCall
|
||||
ldr lr, [sp, #TrPc]
|
||||
add sp, sp, #TrapFrameLength
|
||||
movs pc, lr
|
||||
.else
|
||||
add sp, sp, #TrSvcSp
|
||||
ldmia sp, {sp, lr, pc}^
|
||||
.endif
|
||||
1:
|
||||
b .
|
||||
.endm
|
||||
|
|
104
reactos/ntoskrnl/ke/arm/ke_i.h
Normal file
104
reactos/ntoskrnl/ke/arm/ke_i.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: ntoskrnl/ke/arm/ke_i.h
|
||||
* PURPOSE: Implements macro-generated system call portable wrappers
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
//
|
||||
// First, cleanup after any previous invocation
|
||||
//
|
||||
#undef _1
|
||||
#undef _2
|
||||
#undef _3
|
||||
#undef _4
|
||||
#undef _5
|
||||
#undef _6
|
||||
#undef _7
|
||||
#undef _8
|
||||
#undef _9
|
||||
#undef a
|
||||
#undef b
|
||||
#undef c
|
||||
#undef d
|
||||
#undef e
|
||||
#undef f
|
||||
#undef _10
|
||||
#undef _11
|
||||
#undef SYSCALL
|
||||
|
||||
//
|
||||
// Are we building the typedef prototypes?
|
||||
//
|
||||
#ifdef PROTO
|
||||
//
|
||||
// Then, each parameter is actually a prototype argument
|
||||
//
|
||||
#define _1 PVOID
|
||||
#define _2 PVOID
|
||||
#define _3 PVOID
|
||||
#define _4 PVOID
|
||||
#define _5 PVOID
|
||||
#define _6 PVOID
|
||||
#define _7 PVOID
|
||||
#define _8 PVOID
|
||||
#define _9 PVOID
|
||||
#define a PVOID
|
||||
#define b PVOID
|
||||
#define c PVOID
|
||||
#define d PVOID
|
||||
#define e PVOID
|
||||
#define f PVOID
|
||||
#define _10 PVOID
|
||||
#define _11 PVOID
|
||||
|
||||
//
|
||||
// And we generate the typedef
|
||||
//
|
||||
#define SYSCALL(x, y) typedef NTSTATUS (*PKI_SYSCALL_##x##PARAM)y;
|
||||
|
||||
//
|
||||
// Cleanup for next run
|
||||
//
|
||||
#undef PROTO
|
||||
#else
|
||||
//
|
||||
// Each parameter is actually an argument for the system call
|
||||
//
|
||||
#define _1 g[0x00]
|
||||
#define _2 g[0x01]
|
||||
#define _3 g[0x02]
|
||||
#define _4 g[0x03]
|
||||
#define _5 g[0x04]
|
||||
#define _6 g[0x05]
|
||||
#define _7 g[0x06]
|
||||
#define _8 g[0x07]
|
||||
#define _9 g[0x08]
|
||||
#define a g[0x09]
|
||||
#define b g[0x0A]
|
||||
#define c g[0x0B]
|
||||
#define d g[0x0C]
|
||||
#define e g[0x0D]
|
||||
#define f g[0x0E]
|
||||
#define _10 g[0x0F]
|
||||
#define _11 g[0x10]
|
||||
|
||||
//
|
||||
// And we generate the actual system call
|
||||
//
|
||||
#define SYSCALL(x, y) \
|
||||
NTSTATUS \
|
||||
KiSyscall##x##Param( \
|
||||
IN PVOID p, \
|
||||
IN PVOID *g \
|
||||
) \
|
||||
{ \
|
||||
return ((PKI_SYSCALL_##x##PARAM)p)y; \
|
||||
}
|
||||
|
||||
//
|
||||
// Cleanup for next run
|
||||
//
|
||||
#undef FUNC
|
||||
#endif
|
|
@ -80,7 +80,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
PKPCR Pcr;
|
||||
ULONG i;
|
||||
DPRINT1("[INIT] Process: %p Thread: %p Stack: %p PRCB: %p Number: %d LoaderBlock: %p\n",
|
||||
__FUNCTION__, InitProcess, InitThread, IdleStack, Prcb, Number, LoaderBlock);
|
||||
InitProcess, InitThread, IdleStack, Prcb, Number, LoaderBlock);
|
||||
|
||||
//
|
||||
// Initialize the platform
|
||||
|
|
|
@ -9,284 +9,3 @@ ULONG KeProcessorArchitecture;
|
|||
ULONG KeProcessorLevel;
|
||||
ULONG KeProcessorRevision;
|
||||
ULONG KeFeatureBits;
|
||||
|
||||
|
||||
extern LONG KiTickOffset;
|
||||
extern ULONG KeTimeAdjustment;
|
||||
|
||||
ULONG
|
||||
KiComputeTimerTableIndex(IN LONGLONG DueTime)
|
||||
{
|
||||
ULONG Hand;
|
||||
DPRINT1("DueTime: %I64x Max: %lx\n", DueTime, KeMaximumIncrement);
|
||||
|
||||
//
|
||||
// Compute the timer table index
|
||||
//
|
||||
Hand = (DueTime / KeMaximumIncrement);
|
||||
DPRINT1("HAND: %lx\n", Hand);
|
||||
Hand %= TIMER_TABLE_SIZE;
|
||||
DPRINT1("HAND: %lx\n", Hand);
|
||||
return Hand;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql,
|
||||
IN ULONG Increment)
|
||||
{
|
||||
PKPRCB Prcb = KeGetPcr()->Prcb;
|
||||
ULARGE_INTEGER SystemTime, InterruptTime;
|
||||
ULONG Hand;
|
||||
|
||||
//
|
||||
// Do nothing if this tick is being skipped
|
||||
//
|
||||
if (Prcb->SkipTick)
|
||||
{
|
||||
//
|
||||
// Handle it next time
|
||||
//
|
||||
Prcb->SkipTick = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the increment time to the shared data
|
||||
//
|
||||
InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time;
|
||||
InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart;
|
||||
InterruptTime.QuadPart += Increment;
|
||||
SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart;
|
||||
SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart;
|
||||
SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
|
||||
|
||||
//
|
||||
// Update tick count
|
||||
//
|
||||
KiTickOffset -= Increment;
|
||||
|
||||
//
|
||||
// Check for incomplete tick
|
||||
//
|
||||
if (KiTickOffset <= 0)
|
||||
{
|
||||
//
|
||||
// Update the system time
|
||||
//
|
||||
SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
|
||||
SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
|
||||
SystemTime.QuadPart += KeTimeAdjustment;
|
||||
SharedUserData->SystemTime.High1Time = SystemTime.HighPart;
|
||||
SharedUserData->SystemTime.LowPart = SystemTime.LowPart;
|
||||
SharedUserData->SystemTime.High2Time = SystemTime.HighPart;
|
||||
|
||||
//
|
||||
// Update the tick count
|
||||
//
|
||||
SystemTime.HighPart = KeTickCount.High1Time;
|
||||
SystemTime.LowPart = KeTickCount.LowPart;
|
||||
SystemTime.QuadPart += 1;
|
||||
KeTickCount.High1Time = SystemTime.HighPart;
|
||||
KeTickCount.LowPart = SystemTime.LowPart;
|
||||
KeTickCount.High2Time = SystemTime.HighPart;
|
||||
|
||||
//
|
||||
// Update it in the shared user data
|
||||
//
|
||||
SharedUserData->TickCount.High1Time = SystemTime.HighPart;
|
||||
SharedUserData->TickCount.LowPart = SystemTime.LowPart;
|
||||
SharedUserData->TickCount.High2Time = SystemTime.HighPart;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for timer expiration
|
||||
//
|
||||
Hand = KeTickCount.LowPart % TIMER_TABLE_SIZE;
|
||||
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
|
||||
{
|
||||
//
|
||||
// Timer has expired!
|
||||
//
|
||||
DPRINT1("hand: %d\n", Hand);
|
||||
DPRINT1("Interrupt time: %I64x\n", InterruptTime.QuadPart);
|
||||
DPRINT1("TIMER EXPIRATION: %I64x!!!\n", KiTimerTableListHead[Hand].Time.QuadPart);
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if we should request a debugger break
|
||||
//
|
||||
if (KdDebuggerEnabled)
|
||||
{
|
||||
//
|
||||
// Check if we should break
|
||||
//
|
||||
if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if this was a full tick
|
||||
//
|
||||
if (KiTickOffset <= 0)
|
||||
{
|
||||
//
|
||||
// Updare the tick offset
|
||||
//
|
||||
KiTickOffset += KeMaximumIncrement;
|
||||
|
||||
//
|
||||
// Update system runtime
|
||||
//
|
||||
KeUpdateRunTime(TrapFrame, CLOCK2_LEVEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Increase interrupt count and exit
|
||||
//
|
||||
Prcb->InterruptCount++;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql)
|
||||
{
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
PKPROCESS Process = Thread->ApcState.Process;
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
|
||||
//
|
||||
// Do nothing if this tick is being skipped
|
||||
//
|
||||
if (Prcb->SkipTick)
|
||||
{
|
||||
//
|
||||
// Handle it next time
|
||||
//
|
||||
Prcb->SkipTick = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Increase interrupt count
|
||||
//
|
||||
Prcb->InterruptCount++;
|
||||
|
||||
//
|
||||
// Check if we came from user mode
|
||||
//
|
||||
if (0) //(TrapFrame->PreviousMode != KernelMode)
|
||||
{
|
||||
//
|
||||
// Increase process user time
|
||||
//
|
||||
InterlockedIncrement((PLONG)&Process->UserTime);
|
||||
Prcb->UserTime++;
|
||||
Thread->UserTime++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// See if we were in an ISR
|
||||
//
|
||||
if (TrapFrame->OldIrql > DISPATCH_LEVEL)
|
||||
{
|
||||
//
|
||||
// Handle that
|
||||
//
|
||||
Prcb->InterruptTime++;
|
||||
}
|
||||
else if ((TrapFrame->OldIrql < DISPATCH_LEVEL) ||
|
||||
!(Prcb->DpcRoutineActive))
|
||||
{
|
||||
//
|
||||
// Handle being in kernel mode
|
||||
//
|
||||
Thread->KernelTime++;
|
||||
InterlockedIncrement((PLONG)&Process->KernelTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Handle being in a DPC
|
||||
//
|
||||
Prcb->DpcTime++;
|
||||
|
||||
//
|
||||
// FIXME: Handle DPC checks
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update DPC rates
|
||||
//
|
||||
Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
|
||||
Prcb->DpcRequestRate) >> 1;
|
||||
Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
|
||||
|
||||
//
|
||||
// Check if the queue is large enough
|
||||
//
|
||||
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
|
||||
{
|
||||
//
|
||||
// Request a DPC
|
||||
//
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
|
||||
//
|
||||
// Fix the maximum queue depth
|
||||
//
|
||||
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
|
||||
(Prcb->MaximumDpcQueueDepth > 1))
|
||||
{
|
||||
//
|
||||
// Make it smaller
|
||||
//
|
||||
Prcb->MaximumDpcQueueDepth--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Check if we've reached the adjustment limit
|
||||
//
|
||||
if (!(--Prcb->AdjustDpcThreshold))
|
||||
{
|
||||
//
|
||||
// Reset it, and check the queue maximum
|
||||
//
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
|
||||
{
|
||||
//
|
||||
// Increase it
|
||||
//
|
||||
Prcb->MaximumDpcQueueDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Decrement the thread quantum
|
||||
//
|
||||
Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;
|
||||
|
||||
//
|
||||
// Check if the time expired
|
||||
//
|
||||
if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
|
||||
{
|
||||
//
|
||||
// Schedule a quantum end
|
||||
//
|
||||
Prcb->QuantumEnd = 1;
|
||||
//HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
}
|
||||
|
|
295
reactos/ntoskrnl/ke/arm/time.c
Normal file
295
reactos/ntoskrnl/ke/arm/time.c
Normal file
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: ntoskrnl/ke/arm/time.c
|
||||
* PURPOSE: Implements timebase functionality on ARM processors
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
LONG KiTickOffset;
|
||||
ULONG KeTimeAdjustment;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
ULONG
|
||||
KiComputeTimerTableIndex(IN LONGLONG DueTime)
|
||||
{
|
||||
ULONG Hand;
|
||||
|
||||
//
|
||||
// Compute the timer table index
|
||||
//
|
||||
Hand = (DueTime / KeMaximumIncrement);
|
||||
Hand %= TIMER_TABLE_SIZE;
|
||||
return Hand;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql,
|
||||
IN ULONG Increment)
|
||||
{
|
||||
PKPRCB Prcb = KeGetPcr()->Prcb;
|
||||
ULARGE_INTEGER SystemTime, InterruptTime;
|
||||
ULONG Hand;
|
||||
|
||||
//
|
||||
// Do nothing if this tick is being skipped
|
||||
//
|
||||
if (Prcb->SkipTick)
|
||||
{
|
||||
//
|
||||
// Handle it next time
|
||||
//
|
||||
Prcb->SkipTick = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the increment time to the shared data
|
||||
//
|
||||
InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time;
|
||||
InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart;
|
||||
InterruptTime.QuadPart += Increment;
|
||||
SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart;
|
||||
SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart;
|
||||
SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
|
||||
|
||||
//
|
||||
// Update tick count
|
||||
//
|
||||
KiTickOffset -= Increment;
|
||||
|
||||
//
|
||||
// Check for incomplete tick
|
||||
//
|
||||
if (KiTickOffset <= 0)
|
||||
{
|
||||
//
|
||||
// Update the system time
|
||||
//
|
||||
SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
|
||||
SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
|
||||
SystemTime.QuadPart += KeTimeAdjustment;
|
||||
SharedUserData->SystemTime.High1Time = SystemTime.HighPart;
|
||||
SharedUserData->SystemTime.LowPart = SystemTime.LowPart;
|
||||
SharedUserData->SystemTime.High2Time = SystemTime.HighPart;
|
||||
|
||||
//
|
||||
// Update the tick count
|
||||
//
|
||||
SystemTime.HighPart = KeTickCount.High1Time;
|
||||
SystemTime.LowPart = KeTickCount.LowPart;
|
||||
SystemTime.QuadPart += 1;
|
||||
KeTickCount.High1Time = SystemTime.HighPart;
|
||||
KeTickCount.LowPart = SystemTime.LowPart;
|
||||
KeTickCount.High2Time = SystemTime.HighPart;
|
||||
|
||||
//
|
||||
// Update it in the shared user data
|
||||
//
|
||||
SharedUserData->TickCount.High1Time = SystemTime.HighPart;
|
||||
SharedUserData->TickCount.LowPart = SystemTime.LowPart;
|
||||
SharedUserData->TickCount.High2Time = SystemTime.HighPart;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for timer expiration
|
||||
//
|
||||
Hand = KeTickCount.LowPart % TIMER_TABLE_SIZE;
|
||||
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
|
||||
{
|
||||
//
|
||||
// Timer has expired!
|
||||
//
|
||||
DPRINT1("hand: %d\n", Hand);
|
||||
DPRINT1("Interrupt time: %I64x\n", InterruptTime.QuadPart);
|
||||
DPRINT1("TIMER EXPIRATION: %I64x!!!\n",
|
||||
KiTimerTableListHead[Hand].Time.QuadPart);
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if we should request a debugger break
|
||||
//
|
||||
if (KdDebuggerEnabled)
|
||||
{
|
||||
//
|
||||
// Check if we should break
|
||||
//
|
||||
if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if this was a full tick
|
||||
//
|
||||
if (KiTickOffset <= 0)
|
||||
{
|
||||
//
|
||||
// Updare the tick offset
|
||||
//
|
||||
KiTickOffset += KeMaximumIncrement;
|
||||
|
||||
//
|
||||
// Update system runtime
|
||||
//
|
||||
KeUpdateRunTime(TrapFrame, CLOCK2_LEVEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Increase interrupt count and exit
|
||||
//
|
||||
Prcb->InterruptCount++;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql)
|
||||
{
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
PKPROCESS Process = Thread->ApcState.Process;
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
|
||||
//
|
||||
// Do nothing if this tick is being skipped
|
||||
//
|
||||
if (Prcb->SkipTick)
|
||||
{
|
||||
//
|
||||
// Handle it next time
|
||||
//
|
||||
Prcb->SkipTick = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Increase interrupt count
|
||||
//
|
||||
Prcb->InterruptCount++;
|
||||
|
||||
//
|
||||
// Check if we came from user mode
|
||||
//
|
||||
if (0) //(TrapFrame->PreviousMode != KernelMode)
|
||||
{
|
||||
//
|
||||
// Increase process user time
|
||||
//
|
||||
InterlockedIncrement((PLONG)&Process->UserTime);
|
||||
Prcb->UserTime++;
|
||||
Thread->UserTime++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// See if we were in an ISR
|
||||
//
|
||||
if (TrapFrame->OldIrql > DISPATCH_LEVEL)
|
||||
{
|
||||
//
|
||||
// Handle that
|
||||
//
|
||||
Prcb->InterruptTime++;
|
||||
}
|
||||
else if ((TrapFrame->OldIrql < DISPATCH_LEVEL) ||
|
||||
!(Prcb->DpcRoutineActive))
|
||||
{
|
||||
//
|
||||
// Handle being in kernel mode
|
||||
//
|
||||
Thread->KernelTime++;
|
||||
InterlockedIncrement((PLONG)&Process->KernelTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Handle being in a DPC
|
||||
//
|
||||
Prcb->DpcTime++;
|
||||
|
||||
//
|
||||
// FIXME: Handle DPC checks
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update DPC rates
|
||||
//
|
||||
Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
|
||||
Prcb->DpcRequestRate) >> 1;
|
||||
Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
|
||||
|
||||
//
|
||||
// Check if the queue is large enough
|
||||
//
|
||||
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
|
||||
{
|
||||
//
|
||||
// Request a DPC
|
||||
//
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
|
||||
//
|
||||
// Fix the maximum queue depth
|
||||
//
|
||||
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
|
||||
(Prcb->MaximumDpcQueueDepth > 1))
|
||||
{
|
||||
//
|
||||
// Make it smaller
|
||||
//
|
||||
Prcb->MaximumDpcQueueDepth--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Check if we've reached the adjustment limit
|
||||
//
|
||||
if (!(--Prcb->AdjustDpcThreshold))
|
||||
{
|
||||
//
|
||||
// Reset it, and check the queue maximum
|
||||
//
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
|
||||
{
|
||||
//
|
||||
// Increase it
|
||||
//
|
||||
Prcb->MaximumDpcQueueDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Decrement the thread quantum
|
||||
//
|
||||
Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;
|
||||
|
||||
//
|
||||
// Check if the time expired
|
||||
//
|
||||
if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
|
||||
{
|
||||
//
|
||||
// Schedule a quantum end
|
||||
//
|
||||
Prcb->QuantumEnd = 1;
|
||||
//HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
.title "ARM Trap Dispatching and Handling"
|
||||
.include "ntoskrnl/include/internal/arm/kxarm.h"
|
||||
#include "ntoskrnl/include/internal/arm/kxarm.h"
|
||||
.include "ntoskrnl/include/internal/arm/ksarm.h"
|
||||
|
||||
.global KiArmVectorTable
|
||||
|
@ -28,7 +28,7 @@
|
|||
_KiReservedJump: .word KiReservedException
|
||||
_KiInterruptJump: .word KiInterruptException
|
||||
_KiFastInterruptJump: .word KiFastInterruptException
|
||||
|
||||
|
||||
TEXTAREA
|
||||
NESTED_ENTRY KiUndefinedInstructionException
|
||||
PROLOG_END KiUndefinedInstructionException
|
||||
|
@ -42,76 +42,25 @@
|
|||
|
||||
NESTED_ENTRY KiSoftwareInterruptException
|
||||
PROLOG_END KiSoftwareInterruptException
|
||||
|
||||
//
|
||||
// Save the current lr
|
||||
//
|
||||
str lr, [sp, #-4]!
|
||||
|
||||
//
|
||||
// Save the SVC lr and sp
|
||||
//
|
||||
str lr, [sp, #-4]!
|
||||
str sp, [sp, #-4]!
|
||||
|
||||
//
|
||||
// Make space for trap frame
|
||||
// Handle trap entry
|
||||
//
|
||||
sub sp, sp, #(4*15)
|
||||
|
||||
//
|
||||
// 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]!
|
||||
|
||||
//
|
||||
// Make space for IRQL
|
||||
//
|
||||
sub sp, sp, #4
|
||||
SYSCALL_PROLOG
|
||||
|
||||
//
|
||||
// Call the C handler
|
||||
//
|
||||
adr lr, 1f
|
||||
mov r0, sp
|
||||
bl KiSoftwareInterruptHandler
|
||||
|
||||
//
|
||||
// Skip IRQL
|
||||
//
|
||||
add sp, sp, #(4)
|
||||
ldr pc, =KiSoftwareInterruptHandler
|
||||
|
||||
1:
|
||||
//
|
||||
// Get the SPSR and restore it
|
||||
//
|
||||
ldr r0, [sp], #4
|
||||
msr spsr_all, r0
|
||||
// Handle trap exit
|
||||
//
|
||||
TRAP_EPILOG 1 // FromSystemCall
|
||||
|
||||
//
|
||||
// Restore the registers
|
||||
//
|
||||
ldmia sp, {r0-r14}^
|
||||
mov r0, r0
|
||||
|
||||
//
|
||||
// Advance in the trap frame
|
||||
//
|
||||
add sp, sp, #(4*17)
|
||||
|
||||
//
|
||||
// Restore program execution state
|
||||
//
|
||||
ldr lr, [sp], #4
|
||||
movs pc, lr
|
||||
b .
|
||||
ENTRY_END KiSoftwareInterruptException
|
||||
|
||||
NESTED_ENTRY KiPrefetchAbortException
|
||||
|
@ -128,233 +77,47 @@
|
|||
PROLOG_END KiDataAbortException
|
||||
|
||||
//
|
||||
// Fixup lr
|
||||
// Handle trap entry
|
||||
//
|
||||
sub lr, lr, #8
|
||||
TRAP_PROLOG 1 // FromAbort
|
||||
|
||||
//
|
||||
// Save the bottom 4 registers
|
||||
//
|
||||
stmdb sp, {r0-r3}
|
||||
|
||||
//
|
||||
// Save the abort 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
|
||||
|
||||
//
|
||||
// Save the abort 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]!
|
||||
|
||||
//
|
||||
// Make space for IRQL
|
||||
//
|
||||
sub sp, sp, #4
|
||||
|
||||
//
|
||||
// Call the C handler
|
||||
//
|
||||
adr lr, AbortExit
|
||||
adr lr, 1f
|
||||
mov r0, sp
|
||||
ldr pc, =KiDataAbortHandler
|
||||
|
||||
AbortExit:
|
||||
1:
|
||||
//
|
||||
// Handle trap exit
|
||||
//
|
||||
TRAP_EPILOG 0 // NotFromSystemCall
|
||||
|
||||
//
|
||||
// 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 KiDataAbortException
|
||||
|
||||
NESTED_ENTRY KiInterruptException
|
||||
PROLOG_END KiInterruptException
|
||||
|
||||
//
|
||||
// Handle trap entry
|
||||
//
|
||||
TRAP_PROLOG 0 // NotFromAbort
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
//
|
||||
// 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]!
|
||||
|
||||
//
|
||||
// Make space for IRQL
|
||||
//
|
||||
sub sp, sp, #4
|
||||
|
||||
//
|
||||
// Call the C handler
|
||||
//
|
||||
adr lr, IntExit
|
||||
adr lr, 1f
|
||||
mov r0, sp
|
||||
mov r1, #0
|
||||
ldr pc, =KiInterruptHandler
|
||||
|
||||
IntExit:
|
||||
|
||||
1:
|
||||
//
|
||||
// Skip IRQL
|
||||
//
|
||||
add sp, sp, #(4)
|
||||
|
||||
//
|
||||
// Get the SPSR and restore it
|
||||
//
|
||||
ldr r0, [sp], #4
|
||||
msr spsr_all, r0
|
||||
// Handle trap exit
|
||||
//
|
||||
TRAP_EPILOG 0 // NotFromSystemCall
|
||||
|
||||
//
|
||||
// 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
|
||||
|
@ -377,85 +140,3 @@ IntExit:
|
|||
b .
|
||||
|
||||
ENTRY_END KiReservedException
|
||||
|
||||
|
||||
NESTED_ENTRY KiSystemCall
|
||||
PROLOG_END KiSystemCall
|
||||
|
||||
//
|
||||
// a1 has the function pointer, a2 has an array of arguments, a3 has the count
|
||||
// Save these to better locations
|
||||
//
|
||||
mov r4, a1
|
||||
mov r5, a2
|
||||
mov r6, a3
|
||||
|
||||
//
|
||||
// Load up A1-A4 from the argument array
|
||||
// It doesn't matter if we had less than 4 arguments, we'll be loading some
|
||||
// of the registers with garbage, but nobody will know/care.
|
||||
//
|
||||
ldmia r5, {a1-a4}
|
||||
add r5, r5, #(4* 4)
|
||||
|
||||
//
|
||||
//
|
||||
// This code is complete shit.
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// Save stack address and return address
|
||||
//
|
||||
mov r11, sp
|
||||
mov r10, lr
|
||||
|
||||
//
|
||||
// Check if we have more than 4 arguments
|
||||
//
|
||||
cmp r6, #4
|
||||
ble SysCall
|
||||
|
||||
//
|
||||
// Make space on stack
|
||||
//
|
||||
sub r6, r6, #4
|
||||
sub sp, sp, r6, lsl #2
|
||||
|
||||
CopyLoop:
|
||||
//
|
||||
// Copy one parameter
|
||||
//
|
||||
ldr r7, [r5]
|
||||
str r7, [sp]
|
||||
add r5, r5, #4
|
||||
add sp, sp, #4
|
||||
|
||||
//
|
||||
// Keep looping until we've copied them all
|
||||
//
|
||||
cmp sp, r11
|
||||
bne CopyLoop
|
||||
|
||||
//
|
||||
// Set the stack
|
||||
//
|
||||
sub sp, sp, r6, lsl #2
|
||||
|
||||
//
|
||||
// Now do the system call
|
||||
//
|
||||
SysCall:
|
||||
mov lr, pc
|
||||
mov pc, r4
|
||||
|
||||
//
|
||||
// Restore the stack
|
||||
//
|
||||
mov sp, r11
|
||||
|
||||
//
|
||||
// Get us back
|
||||
//
|
||||
mov pc, r10
|
||||
ENTRY_END KiSystemCall
|
||||
|
|
|
@ -18,13 +18,6 @@
|
|||
#define KiGetPreviousMode(tf) \
|
||||
((tf->Spsr & CPSR_MODES) == CPSR_USER_MODE) ? UserMode: KernelMode
|
||||
|
||||
NTSTATUS
|
||||
KiSystemCall(
|
||||
IN PVOID Handler,
|
||||
IN PULONG Arguments,
|
||||
IN ULONG ArgumentCount
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KiRetireDpcList(
|
||||
|
@ -37,6 +30,13 @@ KiQuantumEnd(
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
KiSystemService(
|
||||
IN PKTHREAD Thread,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN ULONG Instruction
|
||||
);
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
|
@ -237,7 +237,7 @@ KiApcInterrupt(VOID)
|
|||
KPROCESSOR_MODE PreviousMode;
|
||||
KEXCEPTION_FRAME ExceptionFrame;
|
||||
PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
|
||||
DPRINT1("[APC]\n");
|
||||
//DPRINT1("[APC]\n");
|
||||
|
||||
//
|
||||
// Isolate previous mode
|
||||
|
@ -360,6 +360,7 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
|||
ULONG InterruptCause, InterruptMask;
|
||||
PKPCR Pcr;
|
||||
PKTRAP_FRAME OldTrapFrame;
|
||||
ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
|
||||
|
||||
//
|
||||
// Increment interrupt count
|
||||
|
@ -424,7 +425,7 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
|||
// DPRINT1("[ISR RETURN]\n");
|
||||
|
||||
//
|
||||
// Re-enable interrupts and return IRQL
|
||||
// Restore IRQL and interrupts
|
||||
//
|
||||
KeLowerIrql(OldIrql);
|
||||
_enable();
|
||||
|
@ -435,6 +436,7 @@ KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame)
|
|||
{
|
||||
NTSTATUS Status;
|
||||
PVOID Address = (PVOID)KeArmFaultAddressRegisterGet();
|
||||
ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
|
||||
DPRINT1("[ABORT] (%x) @ %p/%p/%p\n",
|
||||
KeArmFaultStatusRegisterGet(), Address, TrapFrame->SvcLr, TrapFrame->Pc);
|
||||
|
||||
|
@ -455,145 +457,13 @@ KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame)
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
KiSystemService(IN PKTHREAD Thread,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN ULONG Instruction)
|
||||
{
|
||||
ULONG Id, Number, ArgumentCount, i;
|
||||
PKPCR Pcr;
|
||||
ULONG_PTR ServiceTable, Offset;
|
||||
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
|
||||
PVOID SystemCall;
|
||||
PULONG Argument;
|
||||
ULONG Arguments[16]; // Maximum 20 arguments
|
||||
|
||||
//
|
||||
// Increase count of system calls
|
||||
//
|
||||
Pcr = (PKPCR)KeGetPcr();
|
||||
Pcr->Prcb->KeSystemCalls++;
|
||||
|
||||
//
|
||||
// Get the system call ID
|
||||
//
|
||||
Id = Instruction & 0xFFFFF;
|
||||
DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode);
|
||||
|
||||
//
|
||||
// Get the descriptor table
|
||||
//
|
||||
ServiceTable = (ULONG_PTR)Thread->ServiceTable;
|
||||
Offset = ((Id >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK);
|
||||
ServiceTable += Offset;
|
||||
DescriptorTable = (PVOID)ServiceTable;
|
||||
|
||||
//
|
||||
// Get the service call number and validate it
|
||||
//
|
||||
Number = Id & SERVICE_NUMBER_MASK;
|
||||
if (Number > DescriptorTable->Limit)
|
||||
{
|
||||
//
|
||||
// Check if this is a GUI call
|
||||
//
|
||||
UNIMPLEMENTED;
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Save the function responsible for handling this system call
|
||||
//
|
||||
SystemCall = (PVOID)DescriptorTable->Base[Number];
|
||||
|
||||
//
|
||||
// Check if this is a GUI call
|
||||
//
|
||||
if (Offset & SERVICE_TABLE_TEST)
|
||||
{
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
UNIMPLEMENTED;
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Check how many arguments this system call takes
|
||||
//
|
||||
ArgumentCount = DescriptorTable->Number[Number] / 4;
|
||||
ASSERT(ArgumentCount <= 20);
|
||||
|
||||
//
|
||||
// Copy the register-arguments first
|
||||
// First four arguments are in a1, a2, a3, a4
|
||||
//
|
||||
Argument = &TrapFrame->R0;
|
||||
for (i = 0; (i < ArgumentCount) && (i < 4); i++)
|
||||
{
|
||||
//
|
||||
// Copy them into the kernel stack
|
||||
//
|
||||
DPRINT1("Argument: %p\n", *Argument);
|
||||
Arguments[i] = *Argument;
|
||||
Argument++;
|
||||
}
|
||||
|
||||
//
|
||||
// If more than four, we'll have some on the user stack
|
||||
//
|
||||
if (ArgumentCount > 4)
|
||||
{
|
||||
//
|
||||
// Check where the stack is
|
||||
//
|
||||
if (Thread->PreviousMode == UserMode)
|
||||
{
|
||||
//
|
||||
// FIXME: Validate the user stack
|
||||
//
|
||||
Argument = (PULONG)TrapFrame->UserSp;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We were called from the kernel
|
||||
//
|
||||
Argument = (PULONG)TrapFrame->SvcSp;
|
||||
|
||||
//
|
||||
// Bias for the values we saved
|
||||
//
|
||||
Argument += 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the rest
|
||||
//
|
||||
for (i = 4; i < ArgumentCount; i++)
|
||||
{
|
||||
//
|
||||
// Copy into kernel stack
|
||||
//
|
||||
DPRINT1("Argument: %p\n", *Argument);
|
||||
Arguments[i] = *Argument;
|
||||
Argument++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do the system call and save result in EAX
|
||||
//
|
||||
TrapFrame->R0 = KiSystemCall(SystemCall, Arguments, ArgumentCount);
|
||||
DPRINT1("Returned: %lx\n", TrapFrame->R0);
|
||||
}
|
||||
|
||||
VOID
|
||||
KiSoftwareInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
PKTHREAD Thread;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
ULONG Instruction;
|
||||
ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
|
||||
|
||||
//
|
||||
// Get the current thread
|
||||
|
@ -606,9 +476,9 @@ KiSoftwareInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
|||
PreviousMode = KiGetPreviousMode(TrapFrame);
|
||||
|
||||
//
|
||||
// FIXME: Save old previous mode
|
||||
// Save old previous mode
|
||||
//
|
||||
//TrapFrame->PreviousMode = PreviousMode;
|
||||
TrapFrame->PreviousMode = PreviousMode;
|
||||
|
||||
//
|
||||
// Save previous mode and trap frame
|
||||
|
|
207
reactos/ntoskrnl/ke/arm/usercall.c
Normal file
207
reactos/ntoskrnl/ke/arm/usercall.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: ntoskrnl/ke/arm/usercall.c
|
||||
* PURPOSE: Implements system calls and user-mode callbacks for ARM
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
//
|
||||
// System call wrapper generator
|
||||
//
|
||||
#define BUILD_SYSCALLS \
|
||||
SYSCALL(00, ()) \
|
||||
SYSCALL(01, (_1)) \
|
||||
SYSCALL(02, (_1, _2)) \
|
||||
SYSCALL(03, (_1, _2, _3)) \
|
||||
SYSCALL(04, (_1, _2, _3, _4 )) \
|
||||
SYSCALL(05, (_1, _2, _3, _4, _5)) \
|
||||
SYSCALL(06, (_1, _2, _3, _4, _5, _6)) \
|
||||
SYSCALL(07, (_1, _2, _3, _4, _5, _6, _7)) \
|
||||
SYSCALL(08, (_1, _2, _3, _4, _5, _6, _7, _8)) \
|
||||
SYSCALL(09, (_1, _2, _3, _4, _5, _6, _7, _8, _9)) \
|
||||
SYSCALL(0A, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a)) \
|
||||
SYSCALL(0B, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b)) \
|
||||
SYSCALL(0C, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c)) \
|
||||
SYSCALL(0D, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d)) \
|
||||
SYSCALL(0E, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e)) \
|
||||
SYSCALL(0F, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f)) \
|
||||
SYSCALL(10, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f, _10)) \
|
||||
SYSCALL(11, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f, _10, _11))
|
||||
|
||||
//
|
||||
// Generate function pointer definitions
|
||||
//
|
||||
#define PROTO
|
||||
#include "ke_i.h"
|
||||
BUILD_SYSCALLS
|
||||
|
||||
//
|
||||
// Generate function code
|
||||
//
|
||||
#define FUNC
|
||||
#include "ke_i.h"
|
||||
BUILD_SYSCALLS
|
||||
|
||||
/* SYSTEM CALL STUBS **********************************************************/
|
||||
|
||||
typedef NTSTATUS (*PKI_SYSCALL_PARAM_HANDLER)(IN PVOID p, IN PVOID *g);
|
||||
PKI_SYSCALL_PARAM_HANDLER KiSyscallHandlers[0x12] =
|
||||
{
|
||||
KiSyscall00Param,
|
||||
KiSyscall01Param,
|
||||
KiSyscall02Param,
|
||||
KiSyscall03Param,
|
||||
KiSyscall04Param,
|
||||
KiSyscall05Param,
|
||||
KiSyscall06Param,
|
||||
KiSyscall07Param,
|
||||
KiSyscall08Param,
|
||||
KiSyscall09Param,
|
||||
KiSyscall0AParam,
|
||||
KiSyscall0BParam,
|
||||
KiSyscall0CParam,
|
||||
KiSyscall0DParam,
|
||||
KiSyscall0EParam,
|
||||
KiSyscall0FParam,
|
||||
KiSyscall10Param,
|
||||
KiSyscall11Param,
|
||||
};
|
||||
|
||||
/* FUNCIONS *******************************************************************/
|
||||
|
||||
VOID
|
||||
KiSystemService(IN PKTHREAD Thread,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN ULONG Instruction)
|
||||
{
|
||||
ULONG Id, Number, ArgumentCount, i;
|
||||
PKPCR Pcr;
|
||||
ULONG_PTR ServiceTable, Offset;
|
||||
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
|
||||
PVOID SystemCall;
|
||||
PVOID* Argument;
|
||||
PVOID Arguments[0x11]; // Maximum 17 arguments
|
||||
ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
|
||||
|
||||
//
|
||||
// Increase count of system calls
|
||||
//
|
||||
Pcr = (PKPCR)KeGetPcr();
|
||||
Pcr->Prcb->KeSystemCalls++;
|
||||
|
||||
//
|
||||
// Get the system call ID
|
||||
//
|
||||
Id = Instruction & 0xFFFFF;
|
||||
//DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode);
|
||||
|
||||
//
|
||||
// Get the descriptor table
|
||||
//
|
||||
ServiceTable = (ULONG_PTR)Thread->ServiceTable;
|
||||
Offset = ((Id >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK);
|
||||
ServiceTable += Offset;
|
||||
DescriptorTable = (PVOID)ServiceTable;
|
||||
|
||||
//
|
||||
// Get the service call number and validate it
|
||||
//
|
||||
Number = Id & SERVICE_NUMBER_MASK;
|
||||
if (Number > DescriptorTable->Limit)
|
||||
{
|
||||
//
|
||||
// Check if this is a GUI call
|
||||
//
|
||||
UNIMPLEMENTED;
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Save the function responsible for handling this system call
|
||||
//
|
||||
SystemCall = (PVOID)DescriptorTable->Base[Number];
|
||||
|
||||
//
|
||||
// Check if this is a GUI call
|
||||
//
|
||||
if (Offset & SERVICE_TABLE_TEST)
|
||||
{
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
UNIMPLEMENTED;
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Check how many arguments this system call takes
|
||||
//
|
||||
ArgumentCount = DescriptorTable->Number[Number] / 4;
|
||||
ASSERT(ArgumentCount <= 20);
|
||||
|
||||
//
|
||||
// Copy the register-arguments first
|
||||
// First four arguments are in a1, a2, a3, a4
|
||||
//
|
||||
Argument = (PVOID*)&TrapFrame->R0;
|
||||
for (i = 0; (i < ArgumentCount) && (i < 4); i++)
|
||||
{
|
||||
//
|
||||
// Copy them into the kernel stack
|
||||
//
|
||||
Arguments[i] = *Argument;
|
||||
Argument++;
|
||||
}
|
||||
|
||||
//
|
||||
// If more than four, we'll have some on the user stack
|
||||
//
|
||||
if (ArgumentCount > 4)
|
||||
{
|
||||
//
|
||||
// Check where the stack is
|
||||
//
|
||||
if (Thread->PreviousMode == UserMode)
|
||||
{
|
||||
//
|
||||
// FIXME: Validate the user stack
|
||||
//
|
||||
ASSERT(FALSE);
|
||||
Argument = (PVOID*)TrapFrame->UserSp;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We were called from the kernel
|
||||
//
|
||||
Argument = (PVOID*)(TrapFrame + 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the rest
|
||||
//
|
||||
for (i = 4; i < ArgumentCount; i++)
|
||||
{
|
||||
//
|
||||
// Copy into kernel stack
|
||||
//
|
||||
Arguments[i] = *Argument;
|
||||
Argument++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do the system call and save result in EAX
|
||||
//
|
||||
TrapFrame->R0 = KiSyscallHandlers[ArgumentCount]((PVOID)SystemCall,
|
||||
(PVOID)Arguments);
|
||||
}
|
|
@ -69,8 +69,10 @@
|
|||
<file>stubs_asm.s</file>
|
||||
<file>stubs.c</file>
|
||||
<file>thrdini.c</file>
|
||||
<file>time.c</file>
|
||||
<file>trap.s</file>
|
||||
<file>trapc.c</file>
|
||||
<file>usercall.c</file>
|
||||
</directory>
|
||||
</if>
|
||||
<if property="ARCH" value="powerpc">
|
||||
|
|
Loading…
Reference in a new issue