2008-03-11 02:45:13 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: ntoskrnl/ke/arm/trapc.c
|
|
|
|
* PURPOSE: Implements the various trap handlers for ARM exceptions
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
2008-03-12 18:17:55 +00:00
|
|
|
#include <internal/arm/ksarm.h>
|
2008-03-11 02:45:13 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
2008-03-12 18:17:55 +00:00
|
|
|
#define KiGetPreviousMode(tf) \
|
|
|
|
((tf->Spsr & CPSR_MODES) == CPSR_USER_MODE) ? UserMode: KernelMode
|
|
|
|
|
2008-03-12 22:06:42 +00:00
|
|
|
NTSTATUS
|
|
|
|
KiSystemCall(
|
|
|
|
IN PVOID Handler,
|
|
|
|
IN PULONG Arguments,
|
|
|
|
IN ULONG ArgumentCount
|
|
|
|
);
|
|
|
|
|
2008-03-11 02:45:13 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
2008-06-14 22:48:30 +00:00
|
|
|
VOID
|
|
|
|
KiIdleLoop(VOID)
|
|
|
|
{
|
|
|
|
PKPCR Pcr = (PKPCR)KeGetPcr();
|
|
|
|
PKPRCB Prcb = Pcr->Prcb;
|
|
|
|
PKTHREAD OldThread, NewThread;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Loop forever... that's why this is an idle loop
|
|
|
|
//
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Cycle interrupts
|
|
|
|
//
|
|
|
|
_disable();
|
|
|
|
_enable();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if there's DPC work to do
|
|
|
|
//
|
|
|
|
if ((Prcb->DpcData[0].DpcQueueDepth) ||
|
|
|
|
(Prcb->TimerRequest) ||
|
|
|
|
(Prcb->DeferredReadyListHead.Next))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Clear the pending interrupt
|
|
|
|
//
|
|
|
|
HalClearSoftwareInterrupt(DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
DPRINT1("DPC/Timer Delivery!\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if there's a thread to schedule
|
|
|
|
//
|
|
|
|
if (Prcb->NextThread)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Out with the old, in with the new...
|
|
|
|
//
|
|
|
|
OldThread = Prcb->CurrentThread;
|
|
|
|
NewThread = Prcb->NextThread;
|
|
|
|
Prcb->CurrentThread = NewThread;
|
|
|
|
Prcb->NextThread = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Update thread state
|
|
|
|
//
|
|
|
|
NewThread->State = Running;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Swap to the new thread
|
|
|
|
// On ARM we call KiSwapContext instead of KiSwapContextInternal,
|
|
|
|
// because we're calling this from C code and not assembly.
|
|
|
|
// This is similar to how it gets called for unwaiting, on x86
|
|
|
|
//
|
|
|
|
DPRINT1("Swapping context!\n");
|
|
|
|
KiSwapContext(OldThread, NewThread);
|
|
|
|
DPRINT1("Back\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: Wait-For-Interrupt ARM Opcode
|
|
|
|
//
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-12 04:32:45 +00:00
|
|
|
BOOLEAN
|
2008-06-11 19:13:25 +00:00
|
|
|
KiSwapContextInternal(IN PKTHREAD OldThread,
|
|
|
|
IN PKTHREAD NewThread)
|
|
|
|
{
|
2008-06-12 00:40:53 +00:00
|
|
|
PKEXCEPTION_FRAME ExFrame = NewThread->KernelStack;
|
2008-06-12 04:32:45 +00:00
|
|
|
PKPCR Pcr = (PKPCR)KeGetPcr();
|
|
|
|
PKPRCB Prcb = Pcr->Prcb;
|
|
|
|
PKPROCESS OldProcess, NewProcess;
|
2008-06-11 19:13:25 +00:00
|
|
|
DPRINT1("Switching from: %p to %p\n", OldThread, NewThread);
|
|
|
|
DPRINT1("Stacks: %p %p\n", OldThread->KernelStack, NewThread->KernelStack);
|
2008-06-12 00:40:53 +00:00
|
|
|
DPRINT1("Thread Registers:\n"
|
|
|
|
"R4: %lx\n"
|
|
|
|
"R5: %lx\n"
|
|
|
|
"R6: %lx\n"
|
|
|
|
"R7: %lx\n"
|
|
|
|
"R8: %lx\n"
|
|
|
|
"R9: %lx\n"
|
|
|
|
"R10: %lx\n"
|
|
|
|
"R11: %lx\n"
|
|
|
|
"Psr: %lx\n"
|
|
|
|
"Lr: %lx\n",
|
|
|
|
ExFrame->R4,
|
|
|
|
ExFrame->R5,
|
|
|
|
ExFrame->R6,
|
|
|
|
ExFrame->R7,
|
|
|
|
ExFrame->R8,
|
|
|
|
ExFrame->R9,
|
|
|
|
ExFrame->R10,
|
|
|
|
ExFrame->R11,
|
|
|
|
ExFrame->Psr,
|
|
|
|
ExFrame->Lr);
|
2008-06-12 04:32:45 +00:00
|
|
|
DPRINT1("Old priority: %lx\n", OldThread->Priority);
|
2008-06-12 00:40:53 +00:00
|
|
|
|
|
|
|
//
|
2008-06-12 04:32:45 +00:00
|
|
|
// Increase context switch count
|
2008-06-12 00:40:53 +00:00
|
|
|
//
|
2008-06-12 04:32:45 +00:00
|
|
|
Pcr->ContextSwitches++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if WMI tracing is enabled
|
|
|
|
//
|
|
|
|
if (Pcr->PerfGlobalGroupMask)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
DPRINT1("WMI Tracing not supported\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if the processes are also different
|
|
|
|
//
|
|
|
|
OldProcess = OldThread->ApcState.Process;
|
|
|
|
NewProcess = NewThread->ApcState.Process;
|
|
|
|
if (OldProcess != NewProcess)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if address space switch is needed
|
|
|
|
//
|
|
|
|
if (OldProcess->DirectoryTableBase.LowPart !=
|
|
|
|
NewProcess->DirectoryTableBase.LowPart)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
DPRINT1("Address space switch not implemented\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Increase thread context switches
|
|
|
|
//
|
|
|
|
NewThread->ContextSwitches++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set us as the current thread
|
|
|
|
// NOTE: On RISC Platforms, there is both a KPCR CurrentThread, and a
|
|
|
|
// KPRCB CurrentThread.
|
|
|
|
// The latter is set just like on x86-based builds, the former is only set
|
|
|
|
// when actually doing the context switch (here).
|
|
|
|
// Recall that the reason for the latter is due to the fact that the KPCR
|
|
|
|
// is shared with user-mode (read-only), so that information is exposed
|
|
|
|
// there as well.
|
|
|
|
//
|
|
|
|
Pcr->CurrentThread = NewThread;
|
|
|
|
|
|
|
|
//
|
|
|
|
// DPCs shouldn't be active
|
|
|
|
//
|
|
|
|
if (Prcb->DpcRoutineActive)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: FAIL
|
|
|
|
//
|
|
|
|
DPRINT1("DPCS ACTIVE!!!\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Kernel APCs may be pending
|
|
|
|
//
|
|
|
|
if (NewThread->ApcState.KernelApcPending)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
DPRINT1("APCs pending!\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Return
|
|
|
|
//
|
|
|
|
return FALSE;
|
2008-06-11 19:13:25 +00:00
|
|
|
}
|
|
|
|
|
2008-06-11 16:48:07 +00:00
|
|
|
VOID
|
|
|
|
KiDispatchInterrupt(VOID)
|
|
|
|
{
|
|
|
|
PKPCR Pcr;
|
2008-06-14 22:48:30 +00:00
|
|
|
PKPRCB Prcb;
|
2008-06-11 16:48:07 +00:00
|
|
|
PKTHREAD NewThread, OldThread;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the PCR and disable interrupts
|
|
|
|
//
|
|
|
|
Pcr = (PKPCR)KeGetPcr();
|
2008-06-14 22:48:30 +00:00
|
|
|
Prcb = Pcr->Prcb;
|
2008-06-11 16:48:07 +00:00
|
|
|
_disable();
|
|
|
|
|
|
|
|
//
|
|
|
|
//Check if we have to deliver DPCs, timers, or deferred threads
|
|
|
|
//
|
2008-06-14 22:48:30 +00:00
|
|
|
if ((Prcb->DpcData[0].DpcQueueDepth) ||
|
|
|
|
(Prcb->TimerRequest) ||
|
|
|
|
(Prcb->DeferredReadyListHead.Next))
|
2008-06-11 16:48:07 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
DPRINT1("DPC/Timer Delivery!\n");
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Re-enable interrupts
|
|
|
|
//
|
|
|
|
_enable();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check for quantum end
|
|
|
|
//
|
2008-06-14 22:48:30 +00:00
|
|
|
if (Prcb->QuantumEnd)
|
2008-06-11 16:48:07 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
DPRINT1("Quantum End!\n");
|
|
|
|
while (TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if we have a thread to swap to
|
|
|
|
//
|
2008-06-14 22:48:30 +00:00
|
|
|
if (Prcb->NextThread)
|
2008-06-14 22:02:50 +00:00
|
|
|
{
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
|
|
|
// Next is now current
|
|
|
|
//
|
2008-06-14 22:48:30 +00:00
|
|
|
OldThread = Prcb->CurrentThread;
|
|
|
|
NewThread = Prcb->NextThread;
|
|
|
|
Prcb->CurrentThread = NewThread;
|
|
|
|
Prcb->NextThread = NULL;
|
2008-06-11 16:48:07 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Update thread states
|
|
|
|
//
|
|
|
|
NewThread->State = Running;
|
|
|
|
OldThread->WaitReason = WrDispatchInt;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make the old thread ready
|
|
|
|
//
|
2008-06-14 22:48:30 +00:00
|
|
|
KxQueueReadyThread(OldThread, Prcb);
|
2008-06-11 16:48:07 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Swap to the new thread
|
2008-06-11 19:13:25 +00:00
|
|
|
// On ARM we call KiSwapContext instead of KiSwapContextInternal,
|
|
|
|
// because we're calling this from C code and not assembly.
|
|
|
|
// This is similar to how it gets called for unwaiting, on x86
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
|
|
|
DPRINT1("Swapping context!\n");
|
2008-06-11 19:13:25 +00:00
|
|
|
KiSwapContext(OldThread, NewThread);
|
2008-06-14 22:48:30 +00:00
|
|
|
DPRINT1("Back\n");
|
2008-06-11 16:48:07 +00:00
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
|
|
|
IN ULONG Reserved)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql, Irql;
|
|
|
|
ULONG InterruptCause, InterruptMask;
|
|
|
|
PKPCR Pcr;
|
2008-06-26 05:56:35 +00:00
|
|
|
PKTRAP_FRAME OldTrapFrame;
|
2008-06-14 22:02:50 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Increment interrupt count
|
|
|
|
//
|
|
|
|
Pcr = (PKPCR)KeGetPcr();
|
|
|
|
Pcr->Prcb->InterruptCount++;
|
2008-06-11 16:48:07 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Get the old IRQL
|
|
|
|
//
|
2008-06-11 18:39:44 +00:00
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
TrapFrame->OldIrql = OldIrql;
|
2008-06-11 16:48:07 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Get the interrupt source
|
|
|
|
//
|
|
|
|
InterruptCause = HalGetInterruptSource();
|
2008-06-14 23:19:03 +00:00
|
|
|
// DPRINT1("[INT] (%x) @ %p %p\n", InterruptCause, TrapFrame->SvcLr, TrapFrame->Pc);
|
2008-06-11 16:48:07 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Get the new IRQL and Interrupt Mask
|
|
|
|
//
|
|
|
|
Irql = Pcr->IrqlMask[InterruptCause];
|
|
|
|
InterruptMask = Pcr->IrqlTable[Irql];
|
|
|
|
|
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
// Raise to the new IRQL
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
KfRaiseIrql(Irql);
|
2008-06-26 05:56:35 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// The clock ISR wants the trap frame as a parameter
|
|
|
|
//
|
|
|
|
OldTrapFrame = KeGetCurrentThread()->TrapFrame;
|
|
|
|
KeGetCurrentThread()->TrapFrame = TrapFrame;
|
2008-06-14 22:02:50 +00:00
|
|
|
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
|
|
|
// Check if this interrupt is at DISPATCH or higher
|
|
|
|
//
|
|
|
|
if (Irql > DISPATCH_LEVEL)
|
2008-06-26 05:56:35 +00:00
|
|
|
{
|
2008-06-14 22:02:50 +00:00
|
|
|
//
|
|
|
|
// FIXME: Switch to interrupt stack
|
|
|
|
//
|
2008-06-14 23:19:03 +00:00
|
|
|
//DPRINT1("[ISR]\n");
|
2008-06-14 22:02:50 +00:00
|
|
|
}
|
|
|
|
else
|
2008-06-11 16:48:07 +00:00
|
|
|
{
|
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
// We know this is APC or DPC.
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
2008-06-14 23:19:03 +00:00
|
|
|
//DPRINT1("[DPC/APC]\n");
|
2008-06-14 22:02:50 +00:00
|
|
|
HalClearSoftwareInterrupt(Irql);
|
2008-06-11 16:48:07 +00:00
|
|
|
}
|
2008-06-26 05:56:35 +00:00
|
|
|
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
// Call the registered interrupt routine
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
Pcr->InterruptRoutine[Irql]();
|
2008-06-26 05:56:35 +00:00
|
|
|
ASSERT(KeGetCurrentThread()->TrapFrame == TrapFrame);
|
|
|
|
KeGetCurrentThread()->TrapFrame = OldTrapFrame;
|
2008-06-14 23:19:03 +00:00
|
|
|
// DPRINT1("[ISR RETURN]\n");
|
2008-06-11 16:48:07 +00:00
|
|
|
|
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
// Re-enable interrupts and return IRQL
|
2008-06-11 16:48:07 +00:00
|
|
|
//
|
2008-06-14 22:02:50 +00:00
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
_enable();
|
2008-06-11 16:48:07 +00:00
|
|
|
}
|
|
|
|
|
2008-03-11 02:45:13 +00:00
|
|
|
NTSTATUS
|
|
|
|
KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame)
|
|
|
|
{
|
2008-03-11 16:13:43 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID Address = (PVOID)KeArmFaultAddressRegisterGet();
|
2008-06-14 22:02:50 +00:00
|
|
|
DPRINT1("[ABORT] (%x) @ %p/%p/%p\n",
|
|
|
|
KeArmFaultStatusRegisterGet(), Address, TrapFrame->SvcLr, TrapFrame->Pc);
|
2008-03-11 16:13:43 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Check if this is a page fault
|
|
|
|
//
|
2008-03-12 00:13:09 +00:00
|
|
|
if (KeArmFaultStatusRegisterGet() == 21 || KeArmFaultStatusRegisterGet() == 23)
|
2008-03-11 16:13:43 +00:00
|
|
|
{
|
|
|
|
Status = MmAccessFault(FALSE,
|
|
|
|
Address,
|
|
|
|
KernelMode,
|
|
|
|
TrapFrame);
|
|
|
|
if (Status == STATUS_SUCCESS) return Status;
|
|
|
|
}
|
2008-03-11 02:45:13 +00:00
|
|
|
|
2008-06-14 22:02:50 +00:00
|
|
|
UNIMPLEMENTED;
|
2008-03-11 02:45:13 +00:00
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-03-12 22:06:42 +00:00
|
|
|
VOID
|
2008-03-12 18:17:55 +00:00
|
|
|
KiSystemService(IN PKTHREAD Thread,
|
|
|
|
IN PKTRAP_FRAME TrapFrame,
|
|
|
|
IN ULONG Instruction)
|
|
|
|
{
|
2008-03-12 22:06:42 +00:00
|
|
|
ULONG Id, Number, ArgumentCount, i;
|
2008-03-12 18:17:55 +00:00
|
|
|
PKPCR Pcr;
|
2008-03-12 22:06:42 +00:00
|
|
|
ULONG_PTR ServiceTable, Offset;
|
|
|
|
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
|
|
|
|
PVOID SystemCall;
|
|
|
|
PULONG Argument;
|
|
|
|
ULONG Arguments[16]; // Maximum 20 arguments
|
2008-03-12 18:17:55 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Increase count of system calls
|
|
|
|
//
|
|
|
|
Pcr = (PKPCR)KeGetPcr();
|
|
|
|
Pcr->Prcb->KeSystemCalls++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the system call ID
|
|
|
|
//
|
|
|
|
Id = Instruction & 0xFFFFF;
|
2008-06-14 22:02:50 +00:00
|
|
|
DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode);
|
2008-03-12 22:06:42 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
2008-06-23 16:08:32 +00:00
|
|
|
DPRINT1("Argument: %p\n", *Argument);
|
2008-03-12 22:06:42 +00:00
|
|
|
Arguments[i] = *Argument;
|
|
|
|
Argument++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If more than four, we'll have some on the user stack
|
|
|
|
//
|
|
|
|
if (ArgumentCount > 4)
|
|
|
|
{
|
|
|
|
//
|
2008-06-15 05:40:27 +00:00
|
|
|
// Check where the stack is
|
2008-03-12 22:06:42 +00:00
|
|
|
//
|
2008-06-15 05:40:27 +00:00
|
|
|
if (Thread->PreviousMode == UserMode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: Validate the user stack
|
|
|
|
//
|
|
|
|
Argument = (PULONG)TrapFrame->UserSp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We were called from the kernel
|
|
|
|
//
|
|
|
|
Argument = (PULONG)TrapFrame->SvcSp;
|
2008-06-23 16:08:32 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Bias for the values we saved
|
|
|
|
//
|
|
|
|
Argument += 2;
|
2008-06-15 05:40:27 +00:00
|
|
|
}
|
|
|
|
|
2008-03-12 22:06:42 +00:00
|
|
|
//
|
|
|
|
// Copy the rest
|
|
|
|
//
|
|
|
|
for (i = 4; i < ArgumentCount; i++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Copy into kernel stack
|
|
|
|
//
|
2008-06-23 16:08:32 +00:00
|
|
|
DPRINT1("Argument: %p\n", *Argument);
|
2008-03-12 22:06:42 +00:00
|
|
|
Arguments[i] = *Argument;
|
|
|
|
Argument++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Do the system call and save result in EAX
|
|
|
|
//
|
|
|
|
TrapFrame->R0 = KiSystemCall(SystemCall, Arguments, ArgumentCount);
|
2008-06-23 16:08:32 +00:00
|
|
|
DPRINT1("Returned: %lx\n", TrapFrame->R0);
|
2008-03-12 18:17:55 +00:00
|
|
|
}
|
|
|
|
|
2008-03-12 22:06:42 +00:00
|
|
|
VOID
|
2008-03-12 18:17:55 +00:00
|
|
|
KiSoftwareInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
|
|
|
{
|
|
|
|
PKTHREAD Thread;
|
|
|
|
KPROCESSOR_MODE PreviousMode;
|
|
|
|
ULONG Instruction;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the current thread
|
|
|
|
//
|
|
|
|
Thread = KeGetCurrentThread();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Isolate previous mode
|
|
|
|
//
|
|
|
|
PreviousMode = KiGetPreviousMode(TrapFrame);
|
|
|
|
|
2008-03-12 22:06:42 +00:00
|
|
|
//
|
|
|
|
// Save old previous mode
|
|
|
|
//
|
|
|
|
//TrapFrame->PreviousMode = PreviousMode;
|
|
|
|
|
2008-03-12 18:17:55 +00:00
|
|
|
//
|
|
|
|
// Save previous mode and trap frame
|
|
|
|
//
|
|
|
|
Thread->TrapFrame = TrapFrame;
|
|
|
|
Thread->PreviousMode = PreviousMode;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read the opcode
|
|
|
|
//
|
|
|
|
Instruction = *(PULONG)(TrapFrame->Pc - sizeof(ULONG));
|
|
|
|
|
2008-03-12 22:06:42 +00:00
|
|
|
//
|
|
|
|
// FIXME: Enable interrupts?
|
|
|
|
//
|
|
|
|
|
2008-03-12 18:17:55 +00:00
|
|
|
//
|
|
|
|
// Call the service call dispatcher
|
|
|
|
//
|
2008-03-12 22:06:42 +00:00
|
|
|
KiSystemService(Thread, TrapFrame, Instruction);
|
2008-03-12 18:17:55 +00:00
|
|
|
}
|