- Fix some bugs in clock.S

- Enable clock.S versions of KeUpdateSystem/RunTime and export them properly.
- Enable systimer.S to call into kernel's KeUpdateSystemTime.
- Enable Hal's Clock Interrupt during Phase 1.
- Remove most of the code that was still left in irq.c
- Only one large problem remains now, which is the spurious firing of the clock interrupt before we're ready to handle it... I will try to fix this today.

svn path=/trunk/; revision=23692
This commit is contained in:
Alex Ionescu 2006-08-24 19:17:14 +00:00
parent d43585136b
commit fe2d752e93
6 changed files with 27 additions and 269 deletions

View file

@ -32,10 +32,6 @@ DriverEntry(
return STATUS_SUCCESS;
}
#define MAKEULONG(x, y) \
(((((ULONG)(x))<<16) & 0xffff0000) | \
((ULONG)(y) & 0xffff))
BOOLEAN STDCALL
HalInitSystem (ULONG BootPhase,
PLOADER_PARAMETER_BLOCK LoaderBlock)
@ -47,14 +43,13 @@ HalInitSystem (ULONG BootPhase,
}
else if (BootPhase == 1)
{
#if 0
/* Enable the clock interrupt */
((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].ExtendedOffset =
(USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF);
((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].Offset =
(USHORT)HalpClockInterrupt;
HalEnableSystemInterrupt(IRQ2VECTOR(0), CLOCK2_LEVEL, Latched);
#endif
/* Initialize display and make the screen black */
HalInitializeDisplay ((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock);
HalpInitBusHandlers();

View file

@ -38,7 +38,8 @@ _HalpClockInterrupt@0:
jz Spurious
/* Do a tick */
//jmp _KeUpdateSystemTime@0
mov eax, 100000
jmp _KeUpdateSystemTime@0
Spurious:

View file

@ -36,13 +36,9 @@ LARGE_INTEGER SystemBootTime = { 0 };
#endif
CHAR KiTimerSystemAuditing = 0;
static KDPC KiExpireTimerDpc;
KDPC KiExpireTimerDpc;
BOOLEAN KiClockSetupComplete = FALSE;
extern ULONG KiMaximumDpcQueueDepth;
extern ULONG KiMinimumDpcRate;
extern ULONG KiAdjustDpcThreshold;
extern ULONG KiIdealDpcRate;
/*
* Number of timer interrupts since initialisation
@ -82,7 +78,7 @@ KiInitializeSystemClock(VOID)
{
TIME_FIELDS TimeFields;
DPRINT("KiInitializeSystemClock()\n");
DPRINT1("KiInitializeSystemClock()\n");
InitializeListHead(&KiTimerListHead);
KeInitializeDpc(&KiExpireTimerDpc, (PKDEFERRED_ROUTINE)KiExpireTimers, 0);
@ -101,7 +97,7 @@ KiInitializeSystemClock(VOID)
SharedUserData->SystemTime.High1Time = SystemBootTime.u.HighPart;
KiClockSetupComplete = TRUE;
DPRINT("Finished KiInitializeSystemClock()\n");
DPRINT1("Finished KiInitializeSystemClock()\n");
}
VOID
@ -234,192 +230,6 @@ KeSetTimeUpdateNotifyRoutine(
UNIMPLEMENTED;
}
/*
* NOTE: On Windows this function takes exactly one parameter and EBP is
* guaranteed to point to KTRAP_FRAME. The function is used only
* by HAL, so there's no point in keeping that prototype.
*
* @implemented
*/
VOID
STDCALL
KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
IN KIRQL Irql)
{
PKPRCB Prcb = KeGetCurrentPrcb();
PKTHREAD CurrentThread = Prcb->CurrentThread;
PKPROCESS CurrentProcess = CurrentThread->ApcState.Process;
/* Increase interrupt count */
Prcb->InterruptCount++;
/* Check if we came from user mode */
if ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
(TrapFrame->SegCs & MODE_MASK))
{
/* Update user times */
CurrentThread->UserTime++;
InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
Prcb->UserTime++;
}
else
{
/* Update CPU kernel time in all cases */
Prcb->KernelTime++;
/* Check IRQ */
if (Irql > DISPATCH_LEVEL)
{
/* This was an interrupt */
Prcb->InterruptTime++;
}
else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
{
/* This was normal kernel time */
CurrentThread->KernelTime++;
InterlockedIncrement((PLONG)&CurrentProcess->KernelTime);
}
else if (Irql == DISPATCH_LEVEL)
{
/* This was DPC time */
Prcb->DpcTime++;
}
}
/* Set the last DPC Count and request rate */
Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
Prcb->DpcRequestRate) / 2;
/* Check if we should request a DPC */
if ((Prcb->DpcData[0].DpcQueueDepth) &&
!(Prcb->DpcRoutineActive) &&
!(Prcb->DpcInterruptRequested))
{
/* Request one */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
/* Update the depth if needed */
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
(Prcb->MaximumDpcQueueDepth > 1))
{
/* Decrease the maximum depth by one */
Prcb->MaximumDpcQueueDepth--;
}
}
else
{
/* Decrease the adjustment threshold */
if (!(--Prcb->AdjustDpcThreshold))
{
/* We've hit 0, reset it */
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
/* Check if we've hit queue maximum */
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
{
/* Increase maximum by one */
Prcb->MaximumDpcQueueDepth++;
}
}
}
/*
* If we're at end of quantum request software interrupt. The rest
* is handled in KiDispatchInterrupt.
*
* NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine
* which checks for quantum end will not be executed and decrementing
* the quantum here can result in overflow. This is not a problem since
* we don't care about the quantum value anymore after the QuantumEnd
* flag is set.
*/
if (((CurrentThread->Quantum -= 3) <= 0) &&
(Prcb->IdleThread != CurrentThread))
{
Prcb->QuantumEnd = TRUE;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
/*
* NOTE: On Windows this function takes exactly zero parameters and EBP is
* guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL.
* The function is used only by HAL, so there's no point in keeping
* that prototype.
*
* @implemented
*/
VOID
STDCALL
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
IN KIRQL Irql,
IN ULONG Increment)
{
LONG OldOffset;
LARGE_INTEGER Time;
ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);
/* Update interrupt time */
Time.LowPart = SharedUserData->InterruptTime.LowPart;
Time.HighPart = SharedUserData->InterruptTime.High1Time;
Time.QuadPart += Increment;
SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
SharedUserData->InterruptTime.High1Time = Time.u.HighPart;
/* Increase the tick offset */
KiTickOffset -= Increment;
OldOffset = KiTickOffset;
/* Check if this isn't a tick yet */
if (KiTickOffset > 0)
{
/* Expire timers */
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
}
else
{
/* Setup time structure for system time */
Time.LowPart = SharedUserData->SystemTime.LowPart;
Time.HighPart = SharedUserData->SystemTime.High1Time;
Time.QuadPart += KeTimeAdjustment;
SharedUserData->SystemTime.High2Time = Time.HighPart;
SharedUserData->SystemTime.LowPart = Time.LowPart;
SharedUserData->SystemTime.High1Time = Time.HighPart;
/* Setup time structure for tick time */
Time.LowPart = KeTickCount.LowPart;
Time.HighPart = KeTickCount.High1Time;
Time.QuadPart += 1;
KeTickCount.High2Time = Time.HighPart;
KeTickCount.LowPart = Time.LowPart;
KeTickCount.High1Time = Time.HighPart;
SharedUserData->TickCount.High2Time = Time.HighPart;
SharedUserData->TickCount.LowPart = Time.LowPart;
SharedUserData->TickCount.High1Time = Time.HighPart;
/* Update tick count in shared user data as well */
SharedUserData->TickCountLowDeprecated++;
/* Queue a DPC that will expire timers */
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
}
/* Update process and thread times */
if (OldOffset <= 0)
{
/* This was a tick, calculate the next one */
KiTickOffset += KeMaximumIncrement;
KeUpdateRunTime(TrapFrame, Irql);
}
/* Return from the interrupt */
Ke386DisableInterrupts();
HalEndSystemInterrupt(Irql, 0);
}
/*
* @implemented
*/

View file

@ -17,12 +17,13 @@
.extern _KiTickOffset
.extern _KeTickCount
.extern _KeMaximumIncrement
.extern _KiExpireTimerDpc
/* FUNCTIONS ******************************************************************/
.globl _KeUpdateRunTime2@0
.func KeUpdateRunTime2@0
_KeUpdateRunTime2@0:
.globl _KeUpdateRunTime@4
.func KeUpdateRunTime@4
_KeUpdateRunTime@4:
/* Get KPCR */
mov eax, [fs:KPCR_SELF]
@ -155,9 +156,9 @@ QuantumNotEmpty:
ret 4
.endfunc
.globl _KeUpdateSystemTime2@0
.func KeUpdateSystemTime2@0
_KeUpdateSystemTime2@0:
.globl _KeUpdateSystemTime@0
.func KeUpdateSystemTime@0
_KeUpdateSystemTime@0:
/* Get shared data in ECX */
mov ecx, USER_SHARED_DATA
@ -185,8 +186,8 @@ _KeUpdateSystemTime2@0:
mov ebx, USER_SHARED_DATA
/* Get system time */
mov edi, [ebx+USER_SHARED_DATA_SYSTEM_TIME]
mov esi, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4]
mov ecx, [ebx+USER_SHARED_DATA_SYSTEM_TIME]
mov edx, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4]
/* Add the increment and get the carry */
add ecx, _KeTimeAdjustment
@ -218,9 +219,16 @@ _KeUpdateSystemTime2@0:
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT], ecx
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+4], edx
/* FIXME: HACK */
mov [USER_SHARED_DATA], ecx
IncompleteTick:
/* Queue DPC to handle registered timers */
/* FIXME: NASTY Queue DPC to handle registered timers */
push 0
push [esp+KTRAP_FRAME_EIP]
push offset _KiExpireTimerDpc
call _KeInsertQueueDpc@12
/* Check if this was a full tick */
cmp dword ptr _KiTickOffset, 0
@ -231,8 +239,8 @@ IncompleteTick:
add _KiTickOffset, eax
/* Update system run time */
push esp
call _KeUpdateRunTime@8
push [esp]
call _KeUpdateRunTime@4
jmp Done
IncompleteTick2:

View file

@ -83,29 +83,6 @@ KeInitInterrupts (VOID)
I486_INTERRUPT_GATE;
}
STATIC VOID
KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
PKTRAP_FRAME TrapFrame)
{
TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs;
TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs;
TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es;
TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds;
TrapFrame->Eax = IrqTrapFrame->Eax;
TrapFrame->Ecx = IrqTrapFrame->Ecx;
TrapFrame->Edx = IrqTrapFrame->Edx;
TrapFrame->Ebx = IrqTrapFrame->Ebx;
TrapFrame->HardwareEsp = IrqTrapFrame->Esp;
TrapFrame->Ebp = IrqTrapFrame->Ebp;
TrapFrame->Esi = IrqTrapFrame->Esi;
TrapFrame->Edi = IrqTrapFrame->Edi;
TrapFrame->Eip = IrqTrapFrame->Eip;
TrapFrame->SegCs = IrqTrapFrame->Cs;
TrapFrame->EFlags = IrqTrapFrame->Eflags;
}
extern BOOLEAN KiClockSetupComplete;
VOID
KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
/*
@ -115,23 +92,6 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
*/
{
KIRQL old_level;
KTRAP_FRAME KernelTrapFrame;
ASSERT(vector == 0x30);
#if 0
PULONG Frame;
DPRINT1("Received Interrupt: %lx\n", vector);
DPRINT1("My trap frame: %p\n", Trapframe);
DPRINT1("Stack trace\n");
__asm__("mov %%ebp, %0" : "=r" (Frame) : );
DPRINT1("Stack trace: %p %p %p %p\n", Frame, *Frame, Frame[1], *(PULONG)Frame[1]);
DPRINT1("Clock setup: %lx\n", KiClockSetupComplete);
if (KiClockSetupComplete) while(TRUE);
#endif
/*
* At this point we have interrupts disabled, nothing has been done to
* the PIC.
*/
KeGetCurrentPrcb()->InterruptCount++;
/*
@ -145,23 +105,7 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
return;
}
/*
* Enable interrupts
* NOTE: Only higher priority interrupts will get through
*/
Ke386EnableInterrupts();
//DPRINT1("Tick\n");
if (KiClockSetupComplete)
{
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
return KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
}
/*
* End the system interrupt.
*/
Ke386DisableInterrupts();
HalEndSystemInterrupt (old_level, 0);
}

View file

@ -647,8 +647,8 @@ KeSynchronizeExecution@12
KeTerminateThread@4
KeTickCount DATA
@KeTryToAcquireGuardedMutex@4
KeUpdateRunTime@8
KeUpdateSystemTime@12
KeUpdateRunTime@4
KeUpdateSystemTime@0
KeUnstackDetachProcess@4
KeUserModeCallback@20
KeWaitForMultipleObjects@32