153 lines
4.7 KiB
NASM
153 lines
4.7 KiB
NASM
|
title "Profile Interrupt"
|
||
|
;++
|
||
|
;
|
||
|
; Copyright (c) 2000 Microsoft Corporation
|
||
|
;
|
||
|
; Module Name:
|
||
|
;
|
||
|
; profint.asm
|
||
|
;
|
||
|
; Abstract:
|
||
|
;
|
||
|
; This module implements the architecture dependent code necessary to
|
||
|
; process the profile interrupt.
|
||
|
;
|
||
|
; Author:
|
||
|
;
|
||
|
; David N. Cutler (davec) 12-Sep-2000
|
||
|
;
|
||
|
; Environment:
|
||
|
;
|
||
|
; Kernel mode only.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
include ksamd64.inc
|
||
|
|
||
|
extern KiProfileListHead:qword
|
||
|
extern KiProfileLock:qword
|
||
|
|
||
|
subttl "Profile Interrupt"
|
||
|
;++
|
||
|
;
|
||
|
; VOID
|
||
|
; KeProfileInterruptWithSource (
|
||
|
; IN KPROFILE_SOURCE ProfileSource
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This routine is executed is response to an interrupt generated by one
|
||
|
; of the profile sources. Its function is to process the system and process
|
||
|
; profile lists and update bucket hit counters.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; TrapFrame (rcx) - Supplies the address of a trap frame.
|
||
|
;
|
||
|
; ProfileSource (rdx) - Supplies the source of profile interrupt.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; None.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
PiFrame struct
|
||
|
Source dq ? ; profile interrupt source
|
||
|
Fill dq ? ; fill to 8 mod 16
|
||
|
SavedRbp dq ? ; saved register RBP
|
||
|
PiFrame ends
|
||
|
|
||
|
NESTED_ENTRY KeProfileInterruptWithSource, _TEXT$00
|
||
|
|
||
|
push_reg rbp ; save nonvolatile register
|
||
|
alloc_stack (sizeof PiFrame - (1 * 8)) ; allocate stack frame
|
||
|
|
||
|
END_PROLOGUE
|
||
|
|
||
|
mov PiFrame.Source[rsp], rdx ; save interrupt source
|
||
|
lea r11, KiProfileLock ; get address of spin lock
|
||
|
AcquireSpinLock r11 ; acquire profile spin lock
|
||
|
mov rcx, PiFrame.Source[rsp] ; set interrupt source
|
||
|
mov rdx, gs:[PcCurrentThread] ; get current thread address
|
||
|
mov rdx, ThApcState + AsProcess[rdx] ; get current process address
|
||
|
add rdx, PrProfileListHead ; compute profile listhead address
|
||
|
call KiProcessProfileList ; process profile list
|
||
|
mov rcx, PiFrame.Source[rsp] ; set interrupt source
|
||
|
lea rdx, KiProfileListHead ; get system profile listhead address
|
||
|
call KiProcessProfileList ; process profile list
|
||
|
lea rcx, KiProfileLock ; get address of spin lock
|
||
|
ReleaseSpinLock r11 ; release spin lock
|
||
|
add rsp, sizeof PiFrame - (1 * 8) ; deallocate stack frame
|
||
|
pop rbp ; restore nonvolatile register
|
||
|
ret ; return
|
||
|
|
||
|
NESTED_END KeProfileInterruptWithSource, _TEXT$00
|
||
|
|
||
|
subttl "Process Profile List"
|
||
|
;++
|
||
|
;
|
||
|
; VOID
|
||
|
; KiProcessProfileList (
|
||
|
; IN KPROFILE_SOURCE Source,
|
||
|
; IN PLIST_ENTRY ListHead
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This routine processes a profile list.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; Source (cx) - Supplies the source of profile interrupt.
|
||
|
;
|
||
|
; ListHead (rdx) - Supplies a pointer to a profile list.
|
||
|
;
|
||
|
; Implicit Arguments:
|
||
|
;
|
||
|
; rbp - Supplies a pointer to a trap frame.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; None.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY KiProcessProfileList, _TEXT$00
|
||
|
|
||
|
mov r8, LsFlink[rdx] ; get first entry address
|
||
|
cmp r8, rdx ; check if list is empty
|
||
|
je short KiPP30 ; if e, list is empty
|
||
|
mov r9, gs:[PcSetMember] ; get procecessor set member
|
||
|
mov r10, TrRip[rbp] ; get profile interrupt address
|
||
|
mov ax, cx ; save profile source
|
||
|
|
||
|
;
|
||
|
; Process list entry.
|
||
|
;
|
||
|
|
||
|
KiPP10: cmp ax, (PfSource - PfProfileListEntry)[r8] ; check for source match
|
||
|
jne short KiPP20 ; if ne, source mismatch
|
||
|
cmp r10, (PfRangeBase - PfProfileListEntry)[r8] ; check if below base
|
||
|
jb short KiPP20 ; if b, address below base
|
||
|
cmp r10, (PfRangeLimit - PfProfileListEntry)[r8] ; check if above limit
|
||
|
jae short KiPP20 ; if ae, address above limit
|
||
|
test r9, (PfAffinity - PfProfileListEntry)[r8] ; check if in set
|
||
|
jz short KiPP20 ; if z, processor not in set
|
||
|
mov cl, (PfBucketShift - PfProfileListEntry)[r8] ; get shift count
|
||
|
mov r11, r10 ; compute offset into profile buffer
|
||
|
sub r11, (PfRangeBase - PfProfileListEntry)[r8] ;
|
||
|
shr r11, cl ;
|
||
|
and r11, NOT 3 ;
|
||
|
mov rcx, (PfBuffer - PfProfileListEntry)[r8] ; get profile buffer address
|
||
|
inc dword ptr [r11][rcx] ; increment profile bucket
|
||
|
KiPP20: mov r8, LsFlink[r8] ; get next entry address
|
||
|
cmp r8, rdx ; check if end of list
|
||
|
jne short KiPP10 ; if ne, not end of list
|
||
|
KiPP30: ret ; return
|
||
|
|
||
|
LEAF_END KiProcessProfileList, _TEXT$00
|
||
|
|
||
|
end
|