123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /*++
- Copyright (c) 2013 Minoca Corp. All Rights Reserved
- Module Name:
- profiler.c
- Abstract:
- This module implements profiler interrupt support at the hardware level.
- Author:
- Chris Stevens 1-Jul-2013
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/kernel.h>
- #include "profiler.h"
- #include "timer.h"
- #include "intrupt.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define the default profiler rate in 100ns. As the profiler is backed by the
- // RTC on x86, the fastest sample rate is 122 microseconds.
- //
- #define DEFAULT_PROFILER_RATE 50000
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Store a variable indicating whether profiler interrupts are broadcasted.
- //
- BOOL HlBroadcastProfilerInterrupts = FALSE;
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- HlStartProfilerTimer (
- VOID
- )
- /*++
- Routine Description:
- This routine activates the profiler by arming the profiler timer.
- Arguments:
- None.
- Return Value:
- Status code.
- --*/
- {
- KSTATUS Status;
- ULONGLONG TickCount;
- //
- // Fail if the profiler timer is not available.
- //
- if (HlProfilerTimer == NULL) {
- return STATUS_NOT_SUPPORTED;
- }
- //
- // Fire up the profiler timer.
- //
- TickCount = HlpTimerTimeToTicks(HlProfilerTimer, DEFAULT_PROFILER_RATE);
- Status = HlpTimerArm(HlProfilerTimer, TimerModePeriodic, TickCount);
- return Status;
- }
- VOID
- HlStopProfilerTimer (
- VOID
- )
- /*++
- Routine Description:
- This routine stops the profiler by disarming the profiler timer.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- //
- // Disarm the profiler timer if it exists.
- //
- if (HlProfilerTimer != NULL) {
- HlpTimerDisarm(HlProfilerTimer);
- }
- return;
- }
- KSTATUS
- HlpTimerInitializeProfiler (
- VOID
- )
- /*++
- Routine Description:
- This routine initializes the system profiler source. It does not start the
- profiler timer.
- Arguments:
- None.
- Return Value:
- Status code.
- --*/
- {
- ULONG Processor;
- PKINTERRUPT ProfilerInterrupt;
- INTERRUPT_LINE_STATE State;
- KSTATUS Status;
- PROCESSOR_SET Target;
- if (HlProfilerTimer == NULL) {
- return STATUS_SUCCESS;
- }
- Processor = KeGetCurrentProcessorNumber();
- if (Processor == 0) {
- //
- // Configure the interrupt for the profiler timer.
- //
- RtlZeroMemory(&Target, sizeof(PROCESSOR_SET));
- Target.Target = ProcessorTargetSelf;
- State.Mode = HlProfilerTimer->Interrupt.TriggerMode;
- State.Polarity = HlProfilerTimer->Interrupt.ActiveLevel;
- State.Flags = INTERRUPT_LINE_STATE_FLAG_ENABLED;
- HlpInterruptGetStandardCpuLine(&(State.Output));
- ProfilerInterrupt = HlpInterruptGetProfilerKInterrupt();
- HlProfilerTimer->InterruptRunLevel = ProfilerInterrupt->RunLevel;
- Status = HlpInterruptSetLineState(&(HlProfilerTimer->Interrupt.Line),
- &State,
- ProfilerInterrupt,
- &Target,
- NULL,
- 0);
- if (!KSUCCESS(Status)) {
- goto InitializeProfilerEnd;
- }
- } else {
- //
- // Always enable broadcast if there are additional processors.
- //
- ASSERT((HlProfilerTimer->Features & TIMER_FEATURE_PER_PROCESSOR) == 0);
- HlBroadcastProfilerInterrupts = TRUE;
- }
- Status = STATUS_SUCCESS;
- InitializeProfilerEnd:
- return Status;
- }
- INTERRUPT_STATUS
- HlpProfilerInterruptHandler (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine is the main profiler ISR.
- Arguments:
- Context - Supplies a pointer to the current trap frame.
- Return Value:
- Claimed always.
- --*/
- {
- ULONG Processor;
- PROCESSOR_SET Processors;
- ASSERT(HlProfilerTimer != NULL);
- //
- // If this is P0, acknowledge the timer and send it off to the other
- // processors if broadcast is set.
- //
- Processor = KeGetCurrentProcessorNumber();
- if (Processor == 0) {
- HlpTimerAcknowledgeInterrupt(HlProfilerTimer);
- if (HlBroadcastProfilerInterrupts != FALSE) {
- Processors.Target = ProcessorTargetAllExcludingSelf;
- HlSendIpi(IpiTypeProfiler, &Processors);
- }
- }
- SpProfilerInterrupt(Context);
- return InterruptStatusClaimed;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
|