NT4/private/ntos/nthals/halws3/i386/w3profil.asm
2020-09-30 17:12:29 +02:00

224 lines
5.1 KiB
NASM

title "Profile Support"
;++
;
; Copyright (c) 1989 Microsoft Corporation
; Copyright (c) 1994 Sequent Computer Systems, Inc.
;
; Module Name:
;
; w3profil.asm
;
; Abstract:
;
; This module implements the code necessary to initialize,
; field, and process the profile interrupt.
;
; Author:
;
; Phil Hochstetler (phil@sequent.com) 3-30-93
;
; Environment:
;
; Kernel mode only.
;
; Revision History:
;
;--
.386p
.xlist
include hal386.inc
include callconv.inc
include i386\kimacro.inc
include mac386.inc
include i386\apic.inc
include i386\ixcmos.inc
include i386\w3.inc
.list
EXTRNP _DbgBreakPoint,0,IMPORT
EXTRNP _KeProfileInterrupt,1,IMPORT
EXTRNP Kei386EoiHelper,0,IMPORT
EXTRNP _HalEndSystemInterrupt,2
EXTRNP _HalBeginSystemInterrupt,3
extrn _HalpLocalUnitBase:DWORD
;
; APIC Timer Constants
;
APIC_TIMER_DISABLED equ (INTERRUPT_MASKED OR PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
APIC_TIMER_ENABLED equ (PERIODIC_TIMER OR APIC_PROFILE_VECTOR)
_DATA SEGMENT DWORD PUBLIC 'DATA'
ProfileCountDownValue dd (200 * 11)
HalpProfileRunning dd 0
_DATA ends
_TEXT SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++
;
; HalStartProfileInterrupt(
; IN ULONG Reserved
; );
;
; Routine Description:
;
; What we do here is set the interrupt rate to the value that's been set
; by the KeSetProfileInterval routine. Then enable the APIC Timer interrupt.
; This function gets called on every processor so the hal can enable
; a profile interrupt on each processor.
;--
cPublicProc _HalStartProfileInterrupt ,1
cPublicFpo 1, 0
mov ecx, _HalpLocalUnitBase ; load base address of local unit
;
; Set the interrupt rate to what is actually needed.
;
mov eax, ProfileCountDownValue
mov [ecx+LU_INITIAL_COUNT], eax
;
; Set the Local APIC Timer to interrupt Periodically at APIC_PROFILE_VECTOR
;
mov [ecx+LU_TIMER_VECTOR], APIC_TIMER_ENABLED
stdRET _HalStartProfileInterrupt
stdENDP _HalStartProfileInterrupt
;++
;
; HalStopProfileInterrupt(
; IN ULONG Reserved
; );
;
; Routine Description:
;
;--
cPublicProc _HalStopProfileInterrupt ,1
cPublicFpo 1, 0
mov ecx, _HalpLocalUnitBase ; load base address of local unit
mov [ecx+LU_TIMER_VECTOR], APIC_TIMER_DISABLED
stdRET _HalStopProfileInterrupt
stdENDP _HalStopProfileInterrupt
;++
; ULONG
; HalSetProfileInterval (
; ULONG Interval
; );
;
; Routine Description:
;
; This procedure sets the interrupt rate (and thus the sampling
; interval) for the profiling interrupt.
;
; Arguments:
;
; (TOS+4) - Interval in 100ns unit.
;
; Return Value:
;
; Interval actually used by system.
;--
cPublicProc _HalSetProfileInterval ,1
cPublicFpo 1, 0
;
; --- On the WinServer 3000, the profile timer uses TBASE on the local APIC
; Timer zero. The TMBASE clock runs at 11Mhz so each clock tick is
; equal to 90.9090ns or roughly 91ns. Since this is close to 100ns
; we will use the 100ns units at the timer counter value directly.
; To use an accurate muliple of 100ns units the profiler would have
; to use 1000ns (1usec) intervals, this interval is equal to 11 clock
; ticks.
;
mov eax, [esp+4] ; ecx = interval in 100ns unit
mov ProfileCountDownValue, eax ; Save the Computed Count Down
mov ecx, _HalpLocalUnitBase ; load base address of local unit
;
; Set the interrupt rate in the chip.
;
mov [ecx+LU_INITIAL_COUNT], eax
stdRET _HalSetProfileInterval
stdENDP _HalSetProfileInterval
page ,132
subttl "System Profile Interrupt"
;++
;
; Routine Description:
;
; This routine is entered as the result of a profile interrupt.
; Its function is to dismiss the interrupt, raise system Irql to
; PROFILE_LEVEL and transfer control to
; the standard system routine to process any active profiles.
;
; Arguments:
;
; None
; Interrupt is disabled
;
; Return Value:
;
; Does not return, jumps directly to KeProfileInterrupt, which returns
;
; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
;
;--
ENTER_DR_ASSIST Hpi_a, Hpi_t
cPublicProc _HalpProfileInterrupt ,0
;
; Save machine state in trap frame
;
ENTER_INTERRUPT Hpi_a, Hpi_t
;
; (esp) - base of trap frame
;
push APIC_PROFILE_VECTOR
sub esp, 4 ; allocate space to save OldIrql
stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,APIC_PROFILE_VECTOR,esp>
or al,al ; check for spurious interrupt
jz Hpi100
stdCall _KeProfileInterrupt,<ebp> ; (ebp) = TrapFrame address
INTERRUPT_EXIT
Hpi100:
add esp, 8 ; spurious, no EndOfInterrupt
SPURIOUS_INTERRUPT_EXIT
stdENDP _HalpProfileInterrupt
_TEXT ends
end