mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 19:31:45 +00:00
- Fix prototype/definition of HalCalibratePerformanceCounter and properly implement it.
- Implement KeStallExecutionProcessor in its own assembly file isntead of using inlined GCC assembly, and align the loop to 16 bytes for more streamlined execution speed. - Mask out clock interrupt during Phase 0 and Initialize clock interrupt on HAL Phase 1. This enables the HAL clock interrupt which was already written. - Make the clock interrupt use HalpCurrentTimeIncrement instead of hardcoding a value. - Re-implement HalpInitializeClock to allow for dynamic increments from 1ms to 15ms with appropriate rollovers and to call KeSetTimeIncrement to update timer values with the kernel. - Implement HalSetTimeIncrement to allow changing the clock ms increment (but this isn't yet respected). - Remove system/runtime update routines from the deprecated IRQ implementation and use the newer assembly ones already written, since we're now using the HAL clock interrupt. Remove other unused code. - Fix more bugs in new hal IRQ implementation (that still isn't used yet due to regressions) and implement HalClearSoftwareInterrupt. svn path=/trunk/; revision=24908
This commit is contained in:
parent
7df718a150
commit
088b3cd98e
12 changed files with 341 additions and 450 deletions
|
@ -173,7 +173,8 @@ HalBeginSystemInterrupt (KIRQL Irql,
|
|||
VOID
|
||||
NTAPI
|
||||
HalCalibratePerformanceCounter(
|
||||
ULONG Count)
|
||||
volatile LONG *Count,
|
||||
ULONGLONG NewCount)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ HalAllocateCommonBuffer@16
|
|||
HalAllocateCrashDumpRegisters@8
|
||||
HalAssignSlotResources@32
|
||||
HalBeginSystemInterrupt@12
|
||||
HalCalibratePerformanceCounter@4
|
||||
HalCalibratePerformanceCounter@12
|
||||
HalDisableSystemInterrupt@8
|
||||
HalDisplayString@4
|
||||
HalEnableSystemInterrupt@12
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<file>sysbus.c</file>
|
||||
<file>sysinfo.c</file>
|
||||
<file>timer.c</file>
|
||||
<file>systimer.S</file>
|
||||
<pch>../include/hal.h</pch>
|
||||
</module>
|
||||
<module name="hal_generic_up" type="objectlibrary">
|
||||
|
@ -28,7 +29,6 @@
|
|||
<file>irql.c</file>
|
||||
<file>processor.c</file>
|
||||
<file>spinlock.c</file>
|
||||
<file>systimer.S</file>
|
||||
</module>
|
||||
<module name="hal_generic_pc" type="objectlibrary">
|
||||
<include base="hal_generic_pc">../include</include>
|
||||
|
|
|
@ -113,7 +113,7 @@ HalInitSystem(IN ULONG BootPhase,
|
|||
HalpInitNonBusHandler();
|
||||
|
||||
/* Initialize the clock interrupt */
|
||||
//HalpInitPhase1();
|
||||
HalpInitPhase1();
|
||||
|
||||
/* Initialize DMA. NT does this in Phase 0 */
|
||||
HalpInitDma();
|
||||
|
|
|
@ -67,18 +67,21 @@ KiI8259MaskTable:
|
|||
.long 0xFFFFFFFB /* IRQL 31 */
|
||||
|
||||
HalpSysIntHandler:
|
||||
.rept 8
|
||||
.rept 7
|
||||
.long GenericIRQ /* IRQ 0-7 */
|
||||
.endr
|
||||
.long IRQ7 /* IRQ 7 */
|
||||
.rept 8
|
||||
.rept 7
|
||||
.long GenericIRQ /* IRQ 8-15 */
|
||||
.endr
|
||||
.long IRQ15 /* IRQ 15 */
|
||||
.rept 20
|
||||
.long GenericIRQ /* IRQ 16-35 */
|
||||
.endr
|
||||
#if DBG
|
||||
.rept 172
|
||||
.long InvalidIRQ /* IRQ 36-207 */
|
||||
#endif
|
||||
.endr
|
||||
|
||||
SoftIntByteTable:
|
||||
|
@ -147,9 +150,22 @@ InitLoop:
|
|||
ret
|
||||
.endfunc
|
||||
|
||||
.globl @HalClearSoftwareInterrupt@4
|
||||
.func @HalClearSoftwareInterrupt@4, @HalClearSoftwareInterrupt@4
|
||||
@HalClearSoftwareInterrupt@4:
|
||||
|
||||
/* Get IRR mask */
|
||||
mov eax, 1
|
||||
shl eax, cl
|
||||
not eax
|
||||
|
||||
/* Set IRR */
|
||||
and PCR[KPCR_IRR], eax
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl @HalRequestSoftwareInterrupt@4
|
||||
.func @HalRequestSoftwareInterrupt@4
|
||||
_@HalRequestSoftwareInterrupt@4:
|
||||
.func @HalRequestSoftwareInterrupt@4, @HalRequestSoftwareInterrupt@4
|
||||
@HalRequestSoftwareInterrupt@4:
|
||||
|
||||
/* Get IRR mask */
|
||||
|
@ -161,11 +177,11 @@ _@HalRequestSoftwareInterrupt@4:
|
|||
cli
|
||||
|
||||
/* Set IRR and get IRQL */
|
||||
or [fs:KPCR_IRR], eax
|
||||
mov ecx, [fs:KPCR_IRQL]
|
||||
or PCR[KPCR_IRR], eax
|
||||
mov ecx, PCR[KPCR_IRQL]
|
||||
|
||||
/* Get software IRR mask */
|
||||
mov eax, [fs:KPCR_IRR]
|
||||
mov eax, PCR[KPCR_IRR]
|
||||
and eax, 3
|
||||
|
||||
/* Get highest pending software interrupt and check if it's higher */
|
||||
|
@ -196,7 +212,7 @@ _HalDisableSystemInterrupt@8:
|
|||
mov edx, 1
|
||||
shl edx, cl
|
||||
cli
|
||||
or [fs:KPCR_IDR], edx
|
||||
or PCR[KPCR_IDR], edx
|
||||
|
||||
/* Get the current mask */
|
||||
xor eax, eax
|
||||
|
@ -263,12 +279,12 @@ AfterMask:
|
|||
shl eax, cl
|
||||
not eax
|
||||
cli
|
||||
and [fs:KPCR_IDR], eax
|
||||
and PCR[KPCR_IDR], eax
|
||||
|
||||
/* Get the current IRQL and mask the IRQs in the PIC */
|
||||
mov eax, [fs:KPCR_IRQL]
|
||||
movzx eax, byte ptr PCR[KPCR_IRQL]
|
||||
mov eax, KiI8259MaskTable[eax*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
@ -281,7 +297,9 @@ AfterMask:
|
|||
Invalid:
|
||||
|
||||
/* Fail, invalid IRQ */
|
||||
#if DBG
|
||||
int 3
|
||||
#endif
|
||||
xor eax, eax
|
||||
ret 12
|
||||
.endfunc
|
||||
|
@ -291,7 +309,7 @@ Invalid:
|
|||
_HalBeginSystemInterrupt@12:
|
||||
|
||||
/* Convert to IRQ and call the handler */
|
||||
mov edx, [esp+8]
|
||||
movzx edx, byte ptr [esp+8]
|
||||
sub edx, PRIMARY_VECTOR_BASE
|
||||
jmp HalpSysIntHandler[edx*4]
|
||||
|
||||
|
@ -326,22 +344,22 @@ IRQ7:
|
|||
GenericIRQ:
|
||||
/* Return the current IRQL */
|
||||
mov eax, [esp+12]
|
||||
mov ecx, [fs:KPCR_IRQL]
|
||||
movzx ecx, byte ptr PCR[KPCR_IRQL]
|
||||
mov [eax], cl
|
||||
|
||||
/* Set the new IRQL */
|
||||
movzx eax, byte ptr [esp+4]
|
||||
mov [fs:KPCR_IRQL], eax
|
||||
mov PCR[KPCR_IRQL], al
|
||||
|
||||
/* Set IRQ mask in the PIC */
|
||||
mov eax, KiI8259MaskTable[eax*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
/* Check to which PIC the EOI was sent */
|
||||
mov eax, ebx
|
||||
mov eax, edx
|
||||
cmp eax, 8
|
||||
jnb Pic1
|
||||
|
||||
|
@ -363,11 +381,13 @@ DoneBegin:
|
|||
sti
|
||||
mov eax, 1
|
||||
ret 12
|
||||
|
||||
|
||||
#if DBG
|
||||
InvalidIRQ:
|
||||
/* Dismiss it */
|
||||
mov eax, 0
|
||||
ret 12
|
||||
#endif
|
||||
.endfunc
|
||||
|
||||
.globl _HalEndSystemInterrupt@8
|
||||
|
@ -376,12 +396,12 @@ _HalEndSystemInterrupt@8:
|
|||
|
||||
/* Get the IRQL and check if it's a software interrupt */
|
||||
movzx ecx, byte ptr [esp+4]
|
||||
cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
cmp byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||
jbe SkipMask2
|
||||
|
||||
/* Hardware interrupt, mask the appropriate IRQs in the PIC */
|
||||
mov eax, KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
@ -389,8 +409,8 @@ _HalEndSystemInterrupt@8:
|
|||
SkipMask2:
|
||||
|
||||
/* Set IRQL and check if there are pending software interrupts */
|
||||
mov [fs:KPCR_IRQL], ecx
|
||||
mov eax, [fs:KPCR_IRR]
|
||||
mov PCR[KPCR_IRQL], cl
|
||||
mov eax, PCR[KPCR_IRR]
|
||||
mov al, SoftIntByteTable[eax]
|
||||
cmp al, cl
|
||||
ja DoCall
|
||||
|
@ -411,15 +431,21 @@ _@KfLowerIrql@4:
|
|||
/* Save flags since we'll disable interrupts */
|
||||
pushf
|
||||
|
||||
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
|
||||
/* Validate IRQL */
|
||||
movzx ecx, cl
|
||||
cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
#if DBG
|
||||
cmp cl, PCR[KPCR_IRQL]
|
||||
ja InvalidIrql
|
||||
#endif
|
||||
|
||||
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
|
||||
cmp byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||
cli
|
||||
jbe SkipMask
|
||||
|
||||
/* Clear interrupt masks since there's a pending hardware interrupt */
|
||||
mov eax, KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
@ -427,8 +453,8 @@ _@KfLowerIrql@4:
|
|||
SkipMask:
|
||||
|
||||
/* Set the new IRQL and check if there's a pending software interrupt */
|
||||
mov [fs:KPCR_IRQL], ecx
|
||||
mov eax, [fs:KPCR_IRR]
|
||||
mov PCR[KPCR_IRQL], cl
|
||||
mov eax, PCR[KPCR_IRR]
|
||||
mov al, SoftIntByteTable[eax]
|
||||
cmp al, cl
|
||||
ja DoCall3
|
||||
|
@ -436,6 +462,22 @@ SkipMask:
|
|||
/* Restore interrupts and return */
|
||||
popf
|
||||
ret
|
||||
|
||||
#if DBG
|
||||
InvalidIrql:
|
||||
/* Set HIGH_LEVEL */
|
||||
movzx eax, byte ptr PCR[KPCR_IRQL]
|
||||
mov byte ptr PCR[KPCR_IRQL], HIGH_LEVEL
|
||||
|
||||
/* Bugcheck the system */
|
||||
push 3
|
||||
push 0
|
||||
push ecx
|
||||
push eax
|
||||
push IRQL_NOT_LESS_OR_EQUAL
|
||||
call _KeBugCheckEx@20
|
||||
#endif
|
||||
|
||||
DoCall3:
|
||||
/* There is, call it */
|
||||
call SoftIntHandlerTable[eax*4]
|
||||
|
@ -450,10 +492,19 @@ DoCall3:
|
|||
_@KfRaiseIrql@4:
|
||||
@KfRaiseIrql@4:
|
||||
|
||||
/* Get the IRQL and check if it's Software level only */
|
||||
mov eax, [fs:KPCR_IRQL]
|
||||
/* Get the IRQL */
|
||||
xor eax, eax
|
||||
mov al, PCR[KPCR_IRQL]
|
||||
movzx ecx, cl
|
||||
cmp ecx, DISPATCH_LEVEL
|
||||
|
||||
#if DBG
|
||||
/* Validate it */
|
||||
cmp eax, ecx
|
||||
ja InvalidKfRaise
|
||||
#endif
|
||||
|
||||
/* Check if it's in the software level */
|
||||
cmp cl, DISPATCH_LEVEL
|
||||
jbe SetIrql
|
||||
|
||||
/* Save the current IRQL */
|
||||
|
@ -464,11 +515,11 @@ _@KfRaiseIrql@4:
|
|||
cli
|
||||
|
||||
/* Set the new IRQL */
|
||||
mov [fs:KPCR_IRQL], cl
|
||||
mov PCR[KPCR_IRQL], cl
|
||||
|
||||
/* Mask the interrupts in the PIC */
|
||||
mov eax, KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
@ -481,8 +532,22 @@ _@KfRaiseIrql@4:
|
|||
SetIrql:
|
||||
|
||||
/* Set the IRQL and return */
|
||||
mov [fs:KPCR_IRQL], ecx
|
||||
mov PCR[KPCR_IRQL], cl
|
||||
ret
|
||||
|
||||
#if DBG
|
||||
InvalidKfRaise:
|
||||
/* Set to passive */
|
||||
mov byte ptr PCR[KPCR_IRQL], PASSIVE_LEVEL
|
||||
|
||||
/* Bugcheck the system */
|
||||
push 9
|
||||
push 0
|
||||
push ecx
|
||||
push eax
|
||||
push IRQL_NOT_GREATER_OR_EQUAL
|
||||
call _KeBugCheckEx@20
|
||||
#endif
|
||||
.endfunc
|
||||
|
||||
.globl _KeGetCurrentIrql@0
|
||||
|
@ -490,7 +555,7 @@ SetIrql:
|
|||
_KeGetCurrentIrql@0:
|
||||
|
||||
/* Return the IRQL */
|
||||
mov eax, [fs:KPCR_IRQL]
|
||||
movzx eax, byte ptr PCR[KPCR_IRQL]
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
@ -499,11 +564,29 @@ _KeGetCurrentIrql@0:
|
|||
_KeRaiseIrqlToDpcLevel@0:
|
||||
|
||||
/* Get the current IRQL */
|
||||
mov eax, [fs:KPCR_IRQL]
|
||||
xor eax, eax
|
||||
mov al, PCR[KPCR_IRQL]
|
||||
|
||||
/* Set DISPATCH_LEVEL */
|
||||
mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
mov byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||
|
||||
#if DBG
|
||||
/* Make sure we were not higher then dispatch */
|
||||
cmp al, DISPATCH_LEVEL
|
||||
ja InvalidRaise
|
||||
#endif
|
||||
ret
|
||||
|
||||
#if DBG
|
||||
InvalidRaise:
|
||||
/* Bugcheck the system */
|
||||
push 1
|
||||
push 0
|
||||
push DISPATCH_LEVEL
|
||||
push eax
|
||||
push IRQL_NOT_GREATER_OR_EQUAL
|
||||
call _KeBugCheckEx@20
|
||||
#endif
|
||||
.endfunc
|
||||
|
||||
.globl _KeRaiseIrqlToSynchLevel@0
|
||||
|
@ -516,16 +599,35 @@ _KeRaiseIrqlToSynchLevel@0:
|
|||
|
||||
/* Mask out interrupts */
|
||||
mov eax, KiI8259MaskTable[DISPATCH_LEVEL*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
/* Return the old IRQL, enable interrupts and set to DISPATCH */
|
||||
mov eax, [fs:KPCR_IRQL]
|
||||
mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
mov al, PCR[KPCR_IRQL]
|
||||
mov byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||
popf
|
||||
|
||||
#if DBG
|
||||
/* Validate raise */
|
||||
cmp al, DISPATCH_LEVEL
|
||||
ja InvalidSyRaise
|
||||
#endif
|
||||
|
||||
/* Return */
|
||||
ret
|
||||
|
||||
#if DBG
|
||||
InvalidSyRaise:
|
||||
/* Bugcheck the system */
|
||||
push 2
|
||||
push 0
|
||||
push DISPATCH_LEVEL
|
||||
push eax
|
||||
push IRQL_NOT_GREATER_OR_EQUAL
|
||||
call _KeBugCheckEx@20
|
||||
#endif
|
||||
.endfunc
|
||||
|
||||
.globl _HalpApcInterrupt
|
||||
|
@ -547,9 +649,9 @@ _HalpApcInterrupt:
|
|||
_HalpApcInterrupt2ndEntry:
|
||||
|
||||
/* Save current IRQL and set to APC level */
|
||||
push [fs:KPCR_IRQL]
|
||||
mov dword ptr [fs:KPCR_IRQL], APC_LEVEL
|
||||
and dword ptr [fs:KPCR_IRR], ~(1 << APC_LEVEL)
|
||||
push PCR[KPCR_IRQL]
|
||||
mov dword ptr PCR[KPCR_IRQL], APC_LEVEL
|
||||
and dword ptr PCR[KPCR_IRR], ~(1 << APC_LEVEL)
|
||||
|
||||
/* Enable interrupts and check if we came from User/V86 mode */
|
||||
sti
|
||||
|
@ -594,9 +696,9 @@ _HalpDispatchInterrupt:
|
|||
_HalpDispatchInterrupt2ndEntry:
|
||||
|
||||
/* Save current IRQL and set to DPC level */
|
||||
push [fs:KPCR_IRQL]
|
||||
mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
and dword ptr [fs:KPCR_IRR], ~(1 << DISPATCH_LEVEL)
|
||||
push PCR[KPCR_IRQL]
|
||||
mov dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||
and dword ptr PCR[KPCR_IRR], ~(1 << DISPATCH_LEVEL)
|
||||
|
||||
/* Enable interrupts and let the kernel handle this */
|
||||
sti
|
||||
|
@ -614,20 +716,20 @@ _HalpEndSoftwareInterrupt@4:
|
|||
|
||||
/* Get the IRQL and check if we're in the software region */
|
||||
movzx ecx, byte ptr [esp+4]
|
||||
cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||
jbe SoftwareInt
|
||||
|
||||
/* Set the right mask in the PIC for the hardware IRQ */
|
||||
mov eax, KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
or eax, PCR[KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
SoftwareInt:
|
||||
/* Check if there are pending software interrupts */
|
||||
mov [fs:KPCR_IRQL], ecx
|
||||
mov eax, [fs:KPCR_IRR]
|
||||
mov PCR[KPCR_IRQL], ecx
|
||||
mov eax, PCR[KPCR_IRR]
|
||||
mov al, SoftIntByteTable[eax]
|
||||
cmp al, cl
|
||||
ja DoCall2
|
||||
|
|
|
@ -96,8 +96,8 @@ VOID NTAPI HalpInitPICs(VOID)
|
|||
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
|
||||
/* Enable interrupts */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, 0xFF);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xFF);
|
||||
|
||||
/* We can now enable interrupts */
|
||||
_enable();
|
||||
|
@ -305,7 +305,7 @@ KeRaiseIrqlToDpcLevel (VOID)
|
|||
KIRQL STDCALL
|
||||
KeRaiseIrqlToSynchLevel (VOID)
|
||||
{
|
||||
return KfRaiseIrql (CLOCK2_LEVEL);
|
||||
return KfRaiseIrql (DISPATCH_LEVEL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -10,9 +10,41 @@
|
|||
#include <asm.h>
|
||||
#include <internal/i386/asmmacro.S>
|
||||
.intel_syntax noprefix
|
||||
.extern _HalpCurrentTimeIncrement
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
.globl _KeStallExecutionProcessor@4
|
||||
.func KeStallExecutionProcessor@4
|
||||
_KeStallExecutionProcessor@4:
|
||||
|
||||
/* Get the number of microseconds required */
|
||||
mov ecx, [esp+4]
|
||||
jecxz Done
|
||||
|
||||
/* Multiply by the stall factor */
|
||||
mov eax, fs:[KPCR_STALL_SCALE_FACTOR]
|
||||
mul ecx
|
||||
|
||||
/* Align to 16 bytes */
|
||||
.align 16
|
||||
|
||||
/* Jump to subtraction loop */
|
||||
jmp SubtractLoop
|
||||
|
||||
/* Align to 16 bytes */
|
||||
.align 16
|
||||
|
||||
/* Subtract one count */
|
||||
SubtractLoop:
|
||||
sub eax, 1
|
||||
jnz SubtractLoop
|
||||
|
||||
Done:
|
||||
/* Return */
|
||||
ret 4
|
||||
.endfunc
|
||||
|
||||
.globl _HalpClockInterrupt@0
|
||||
.func HalpClockInterrupt@0
|
||||
_HalpClockInterrupt@0:
|
||||
|
@ -35,7 +67,8 @@ _HalpClockInterrupt@0:
|
|||
jz Spurious
|
||||
|
||||
/* Do a tick */
|
||||
mov eax, 100000
|
||||
mov eax, _HalpCurrentTimeIncrement
|
||||
xor ebx, ebx
|
||||
jmp _KeUpdateSystemTime@0
|
||||
|
||||
Spurious:
|
||||
|
|
|
@ -38,127 +38,146 @@
|
|||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
#define TMR_CTRL 0x43 /* I/O for control */
|
||||
#define TMR_CNT0 0x40 /* I/O for counter 0 */
|
||||
#define TMR_CNT1 0x41 /* I/O for counter 1 */
|
||||
#define TMR_CNT2 0x42 /* I/O for counter 2 */
|
||||
|
||||
#define TMR_SC0 0 /* Select channel 0 */
|
||||
#define TMR_SC1 0x40 /* Select channel 1 */
|
||||
#define TMR_SC2 0x80 /* Select channel 2 */
|
||||
|
||||
#define TMR_LOW 0x10 /* RW low byte only */
|
||||
#define TMR_HIGH 0x20 /* RW high byte only */
|
||||
#define TMR_BOTH 0x30 /* RW both bytes */
|
||||
|
||||
#define TMR_MD0 0 /* Mode 0 */
|
||||
#define TMR_MD1 0x2 /* Mode 1 */
|
||||
#define TMR_MD2 0x4 /* Mode 2 */
|
||||
#define TMR_MD3 0x6 /* Mode 3 */
|
||||
#define TMR_MD4 0x8 /* Mode 4 */
|
||||
#define TMR_MD5 0xA /* Mode 5 */
|
||||
|
||||
#define TMR_BCD 1 /* BCD mode */
|
||||
|
||||
#define TMR_LATCH 0 /* Latch command */
|
||||
|
||||
#define TMR_READ 0xF0 /* Read command */
|
||||
#define TMR_CNT 0x20 /* CNT bit (Active low, subtract it) */
|
||||
#define TMR_STAT 0x10 /* Status bit (Active low, subtract it) */
|
||||
#define TMR_CH2 0x8 /* Channel 2 bit */
|
||||
#define TMR_CH1 0x4 /* Channel 1 bit */
|
||||
#define TMR_CH0 0x2 /* Channel 0 bit */
|
||||
|
||||
#define MILLISEC 10 /* Number of millisec between interrupts */
|
||||
#define HZ (1000 / MILLISEC) /* Number of interrupts per second */
|
||||
#define CLOCK_TICK_RATE 1193182 /* Clock frequency of the timer chip */
|
||||
#define LATCH (CLOCK_TICK_RATE / HZ) /* Count to program into the timer chip */
|
||||
#define PRECISION 8 /* Number of bits to calibrate for delay loop */
|
||||
|
||||
static BOOLEAN UdelayCalibrated = FALSE;
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS **************************************************************/
|
||||
BOOLEAN HalpClockSetMSRate;
|
||||
ULONG HalpCurrentTimeIncrement;
|
||||
ULONG HalpCurrentRollOver;
|
||||
ULONG HalpNextMSRate = 14;
|
||||
ULONG HalpLargestClockMS = 15;
|
||||
|
||||
/*
|
||||
* NOTE: This function MUST NOT be optimized by the compiler!
|
||||
* If it is, it obviously will not delay AT ALL, and the system
|
||||
* will appear completely frozen at boot since
|
||||
* HalpCalibrateStallExecution will never return.
|
||||
* There are three options to stop optimization:
|
||||
* 1. Use a volatile automatic variable. Making it delay quite a bit
|
||||
* due to memory accesses, and keeping the code portable. However,
|
||||
* as this involves memory access it depends on both the CPU cache,
|
||||
* e.g. if the stack used is already in a cache line or not, and
|
||||
* whether or not we're MP. If MP, another CPU could (probably would)
|
||||
* also access RAM at the same time - making the delay imprecise.
|
||||
* 2. Use compiler-specific #pragma's to disable optimization.
|
||||
* 3. Use inline assembly, making it equally unportable as #2.
|
||||
* For supported compilers we use inline assembler. For the others,
|
||||
* portable plain C.
|
||||
*/
|
||||
DECLSPEC_NOINLINE VOID STDCALL
|
||||
__KeStallExecutionProcessor(ULONG Loops)
|
||||
LARGE_INTEGER HalpRolloverTable[15] =
|
||||
{
|
||||
if (!Loops)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
__asm__ __volatile__ (
|
||||
"mov %0, %%eax\n"
|
||||
"ROSL1: dec %%eax\n"
|
||||
"jnz ROSL1" : : "d" (Loops));
|
||||
{{1197, 10032}},
|
||||
{{2394, 20064}},
|
||||
{{3591, 30096}},
|
||||
{{4767, 39952}},
|
||||
{{5964, 49984}},
|
||||
{{7161, 60016}},
|
||||
{{8358, 70048}},
|
||||
{{9555, 80080}},
|
||||
{{10731, 89936}},
|
||||
{{11949, 100144}},
|
||||
{{13125, 110000}},
|
||||
{{14322, 120032}},
|
||||
{{15519, 130064}},
|
||||
{{16695, 139920}},
|
||||
{{17892, 149952}}
|
||||
};
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
__asm mov eax, Loops
|
||||
ROSL1:
|
||||
__asm dec eax
|
||||
__asm jnz ROSL1
|
||||
#else
|
||||
unsigned int target = Loops;
|
||||
volatile unsigned int i;
|
||||
for (i=0; i<target;i++);
|
||||
#endif
|
||||
}
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
KeStallExecutionProcessor(ULONG Microseconds)
|
||||
NTAPI
|
||||
HalpInitializeClock(VOID)
|
||||
{
|
||||
PKIPCR Pcr = (PKIPCR)KeGetPcr();
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
ULONG Increment;
|
||||
USHORT RollOver;
|
||||
|
||||
if (Pcr->PrcbData.FeatureBits & KF_RDTSC)
|
||||
{
|
||||
LARGE_INTEGER EndCount, CurrentCount;
|
||||
EndCount.QuadPart = (LONGLONG)__rdtsc();
|
||||
EndCount.QuadPart += Microseconds * (ULONGLONG)Pcr->PrcbData.MHz;
|
||||
do
|
||||
{
|
||||
CurrentCount.QuadPart = (LONGLONG)__rdtsc();
|
||||
}
|
||||
while (CurrentCount.QuadPart < EndCount.QuadPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
__KeStallExecutionProcessor((Pcr->StallScaleFactor*Microseconds)/1000);
|
||||
}
|
||||
/* Check the CPU Type */
|
||||
if (Prcb->CpuType <= 4)
|
||||
{
|
||||
/* 486's or equal can't go higher then 10ms */
|
||||
HalpLargestClockMS = 10;
|
||||
HalpNextMSRate = 9;
|
||||
}
|
||||
|
||||
/* Get increment and rollover for the largest time clock ms possible */
|
||||
Increment= HalpRolloverTable[HalpLargestClockMS - 1].HighPart;
|
||||
RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart;
|
||||
|
||||
/* Set the maximum and minimum increment with the kernel */
|
||||
HalpCurrentTimeIncrement = Increment;
|
||||
KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart);
|
||||
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
|
||||
/* Set the rollover */
|
||||
__outbyte(TIMER_CONTROL_PORT, TIMER_SC0 | TIMER_BOTH | TIMER_MD2);
|
||||
__outbyte(TIMER_DATA_PORT0, RollOver & 0xFF);
|
||||
__outbyte(TIMER_DATA_PORT0, RollOver >> 8);
|
||||
|
||||
/* Restore interrupts */
|
||||
_enable();
|
||||
|
||||
/* Save rollover and return */
|
||||
HalpCurrentRollOver = RollOver;
|
||||
}
|
||||
|
||||
static ULONG Read8254Timer(VOID)
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
HalCalibratePerformanceCounter(IN volatile PLONG Count,
|
||||
IN ULONGLONG NewCount)
|
||||
{
|
||||
ULONG Count;
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
/* Do a decrement for this CPU */
|
||||
//_InterlockedDecrement(Count);
|
||||
InterlockedDecrement(Count);
|
||||
|
||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_LATCH);
|
||||
Count = READ_PORT_UCHAR((PUCHAR) TMR_CNT0);
|
||||
Count |= READ_PORT_UCHAR((PUCHAR) TMR_CNT0) << 8;
|
||||
/* Wait for other CPUs */
|
||||
while (*Count);
|
||||
|
||||
_enable();
|
||||
return Count;
|
||||
/* Bring interrupts back */
|
||||
_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG
|
||||
NTAPI
|
||||
HalSetTimeIncrement(IN ULONG Increment)
|
||||
{
|
||||
/* Round increment to ms */
|
||||
Increment /= 10000;
|
||||
|
||||
/* Normalize between our minimum (1 ms) and maximum (variable) setting */
|
||||
if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS;
|
||||
if (Increment < 0) Increment = 1;
|
||||
|
||||
/* Set the rate and tell HAL we want to change it */
|
||||
HalpNextMSRate = Increment;
|
||||
HalpClockSetMSRate = TRUE;
|
||||
|
||||
/* Return the increment */
|
||||
return HalpRolloverTable[Increment - 1].HighPart;
|
||||
}
|
||||
|
||||
/* STUFF *********************************************************************/
|
||||
|
||||
ULONG
|
||||
FORCEINLINE
|
||||
Read8254Timer(VOID)
|
||||
{
|
||||
ULONG Count;
|
||||
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
|
||||
/* Set the rollover */
|
||||
__outbyte(TIMER_CONTROL_PORT, TIMER_SC0);
|
||||
Count = __inbyte(TIMER_DATA_PORT0);
|
||||
Count |= __inbyte(TIMER_DATA_PORT0) << 8;
|
||||
|
||||
/* Restore interrupts and return count*/
|
||||
_enable();
|
||||
return Count;
|
||||
}
|
||||
|
||||
VOID WaitFor8254Wraparound(VOID)
|
||||
{
|
||||
|
@ -183,20 +202,6 @@ VOID WaitFor8254Wraparound(VOID)
|
|||
while (Delta < 300);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpInitializeClock(VOID)
|
||||
{
|
||||
/* FIXME: Make dynamic */
|
||||
|
||||
/* Initialize the clock */
|
||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_BOTH | TMR_MD2); /* binary, mode 2, LSB/MSB, ch 0 */
|
||||
|
||||
/* Set the increment */
|
||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CNT0, LATCH & 0xff); /* LSB */
|
||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CNT0, LATCH >> 8); /* MSB */
|
||||
}
|
||||
|
||||
VOID HalpCalibrateStallExecution(VOID)
|
||||
{
|
||||
ULONG i;
|
||||
|
@ -205,12 +210,6 @@ VOID HalpCalibrateStallExecution(VOID)
|
|||
PKIPCR Pcr;
|
||||
LARGE_INTEGER StartCount, EndCount;
|
||||
|
||||
if (UdelayCalibrated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UdelayCalibrated = TRUE;
|
||||
Pcr = (PKIPCR)KeGetPcr();
|
||||
|
||||
if (Pcr->PrcbData.FeatureBits & KF_RDTSC)
|
||||
|
@ -242,7 +241,7 @@ VOID HalpCalibrateStallExecution(VOID)
|
|||
|
||||
WaitFor8254Wraparound();
|
||||
|
||||
__KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||
KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||
|
||||
CurCount = Read8254Timer();
|
||||
}
|
||||
|
@ -267,7 +266,7 @@ VOID HalpCalibrateStallExecution(VOID)
|
|||
|
||||
WaitFor8254Wraparound();
|
||||
|
||||
__KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||
KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||
|
||||
CurCount = Read8254Timer();
|
||||
if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
|
||||
|
@ -295,19 +294,6 @@ VOID HalpCalibrateStallExecution(VOID)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
HalCalibratePerformanceCounter(ULONG Count)
|
||||
{
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
|
||||
__KeStallExecutionProcessor(Count);
|
||||
|
||||
_enable();
|
||||
}
|
||||
|
||||
|
||||
LARGE_INTEGER
|
||||
STDCALL
|
||||
KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
|
||||
|
@ -360,12 +346,4 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
|
|||
return Value;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
HalSetTimeIncrement(IN ULONG Increment)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
return Increment;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -22,6 +22,13 @@
|
|||
#define RTC_REG_A_UIP 0x80
|
||||
#define RTC_REGISTER_CENTURY 0x32
|
||||
|
||||
/* Timer Registers and Ports */
|
||||
#define TIMER_CONTROL_PORT 0x43
|
||||
#define TIMER_DATA_PORT0 0x40
|
||||
#define TIMER_SC0 0
|
||||
#define TIMER_BOTH 0x30
|
||||
#define TIMER_MD2 0x4
|
||||
|
||||
/* Conversion functions */
|
||||
#define BCD_INT(bcd) \
|
||||
(((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F))
|
||||
|
|
|
@ -20,6 +20,17 @@ Author:
|
|||
#ifndef _ASM_H
|
||||
#define _ASM_H
|
||||
|
||||
//
|
||||
// PCR Access
|
||||
//
|
||||
#ifdef __ASM__
|
||||
#ifdef CONFIG_SMP
|
||||
#define PCR fs:
|
||||
#else
|
||||
#define PCR ds:[0xFF000000]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// CPU Modes
|
||||
//
|
||||
|
@ -145,6 +156,7 @@ Author:
|
|||
#define KPCR_IDT 0x38
|
||||
#define KPCR_GDT 0x3C
|
||||
#define KPCR_TSS 0x40
|
||||
#define KPCR_STALL_SCALE_FACTOR 0x4C
|
||||
#define KPCR_SET_MEMBER 0x48
|
||||
#define KPCR_NUMBER 0x51
|
||||
#define KPCR_PRCB_DATA 0x120
|
||||
|
@ -489,6 +501,8 @@ Author:
|
|||
#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
|
||||
#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
|
||||
#define APC_INDEX_MISMATCH 0x01
|
||||
#define IRQL_NOT_GREATER_OR_EQUAL 0x09
|
||||
#define IRQL_NOT_LESS_OR_EQUAL 0x0A
|
||||
#define TRAP_CAUSE_UNKNOWN 0x12
|
||||
#define KMODE_EXCEPTION_NOT_HANDLED 0x13
|
||||
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
|
||||
|
|
|
@ -177,231 +177,6 @@ KeInitInterrupts (VOID)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static VOID
|
||||
KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
|
||||
PKIRQ_TRAPFRAME IrqTrapFrame)
|
||||
{
|
||||
IrqTrapFrame->Gs = TrapFrame->SegGs;
|
||||
IrqTrapFrame->Fs = TrapFrame->SegFs;
|
||||
IrqTrapFrame->Es = TrapFrame->SegEs;
|
||||
IrqTrapFrame->Ds = TrapFrame->SegDs;
|
||||
IrqTrapFrame->Eax = TrapFrame->Eax;
|
||||
IrqTrapFrame->Ecx = TrapFrame->Ecx;
|
||||
IrqTrapFrame->Edx = TrapFrame->Edx;
|
||||
IrqTrapFrame->Ebx = TrapFrame->Ebx;
|
||||
IrqTrapFrame->Esp = TrapFrame->HardwareEsp;
|
||||
IrqTrapFrame->Ebp = TrapFrame->Ebp;
|
||||
IrqTrapFrame->Esi = TrapFrame->Esi;
|
||||
IrqTrapFrame->Edi = TrapFrame->Edi;
|
||||
IrqTrapFrame->Eip = TrapFrame->Eip;
|
||||
IrqTrapFrame->Cs = TrapFrame->SegCs;
|
||||
IrqTrapFrame->Eflags = TrapFrame->EFlags;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
PKPROCESS CurrentProcess;
|
||||
|
||||
/* Make sure we don't go further if we're in early boot phase. */
|
||||
if (!(Prcb) || !(Prcb->CurrentThread)) return;
|
||||
|
||||
/* Get the current thread and process */
|
||||
CurrentThread = Prcb->CurrentThread;
|
||||
CurrentProcess = CurrentThread->ApcState.Process;
|
||||
|
||||
/* Check if we came from user mode */
|
||||
if (TrapFrame->PreviousPreviousMode != KernelMode)
|
||||
{
|
||||
/* Update user times */
|
||||
CurrentThread->UserTime++;
|
||||
InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
|
||||
Prcb->UserTime++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* Update CPU kernel time in all cases */
|
||||
Prcb->KernelTime++;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
/* 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->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);
|
||||
if (!KiClockSetupComplete) return;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
|
||||
/*
|
||||
|
@ -453,9 +228,7 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
|||
*/
|
||||
{
|
||||
KIRQL old_level;
|
||||
KTRAP_FRAME KernelTrapFrame;
|
||||
PKTHREAD CurrentThread;
|
||||
PKTRAP_FRAME OldTrapFrame=NULL;
|
||||
|
||||
/*
|
||||
* At this point we have interrupts disabled, nothing has been done to
|
||||
|
@ -482,20 +255,12 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
|||
*/
|
||||
_enable();
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
if (VECTOR2IRQ(vector) == 0)
|
||||
{
|
||||
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
||||
KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ASSERT (VECTOR2IRQ(vector) != 0);
|
||||
|
||||
/*
|
||||
* Actually call the ISR.
|
||||
*/
|
||||
KiInterruptDispatch2(vector, old_level);
|
||||
}
|
||||
|
||||
/*
|
||||
* End the system interrupt.
|
||||
|
@ -514,23 +279,14 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
|||
((PETHREAD)CurrentThread)->Cid.UniqueThread,
|
||||
Trapframe->Cs,
|
||||
CurrentThread->TrapFrame ? CurrentThread->TrapFrame->SegCs : 0);
|
||||
if (CurrentThread->TrapFrame == NULL)
|
||||
{
|
||||
OldTrapFrame = CurrentThread->TrapFrame;
|
||||
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
||||
CurrentThread->TrapFrame = &KernelTrapFrame;
|
||||
}
|
||||
ASSERT (CurrentThread->TrapFrame);
|
||||
|
||||
_enable();
|
||||
KiDeliverApc(UserMode, NULL, NULL);
|
||||
_disable();
|
||||
|
||||
ASSERT(KeGetCurrentThread() == CurrentThread);
|
||||
if (CurrentThread->TrapFrame == &KernelTrapFrame)
|
||||
{
|
||||
KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
|
||||
CurrentThread->TrapFrame = OldTrapFrame;
|
||||
}
|
||||
ASSERT (CurrentThread->TrapFrame);
|
||||
}
|
||||
KeLowerIrql(PASSIVE_LEVEL);
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
|
|||
|
||||
/* Set the system affinity and acquire the dispatcher lock */
|
||||
KeSetSystemAffinityThread(1 << Number);
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
OldIrql = KiAcquireDispatcherLock();
|
||||
|
||||
/* Check if it's already been connected */
|
||||
if (!Interrupt->Connected)
|
||||
|
@ -272,7 +272,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
|
|||
}
|
||||
|
||||
/* Unlock the dispatcher and revert affinity */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
KiReleaseDispatcherLock(OldIrql);
|
||||
KeRevertToUserAffinityThread();
|
||||
|
||||
/* Return to caller */
|
||||
|
@ -296,7 +296,7 @@ KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
|
|||
KeSetSystemAffinityThread(1 << Interrupt->Number);
|
||||
|
||||
/* Lock the dispatcher */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
OldIrql = KiAcquireDispatcherLock();
|
||||
|
||||
/* Check if it's actually connected */
|
||||
State = Interrupt->Connected;
|
||||
|
@ -354,7 +354,7 @@ KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
|
|||
}
|
||||
|
||||
/* Unlock the dispatcher and revert affinity */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
KiReleaseDispatcherLock(OldIrql);
|
||||
KeRevertToUserAffinityThread();
|
||||
|
||||
/* Return to caller */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue