Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1647 lines
40 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. i64prfle.c
  5. Abstract:
  6. This module implements the IA64 Hal Profiling using the performance
  7. counters within the core of the first IA64 Processor Merced, aka Itanium.
  8. This module is appropriate for all machines based on microprocessors using
  9. the Merced core.
  10. With the information known at this development time, this module tries to
  11. consider the future IA64 processor cores by encapsulating the differences
  12. in specific micro-architecture data structures.
  13. Furthermore, with the implementation of the new NT ACPI Processor driver, this
  14. implementation will certainly change in the coming months.
  15. N.B. - This module assumes that all processors in a multiprocessor
  16. system are running the microprocessor at the same clock speed.
  17. Author:
  18. Thierry Fevrier 08-Feb-2000
  19. Environment:
  20. Kernel mode only.
  21. Revision History:
  22. --*/
  23. #include "halp.h"
  24. //
  25. // Assumptions for the current implementation - 02/08/2000 :
  26. // These assumptions will be re-evaluated and worked out if required.
  27. //
  28. // - Respect and satisfy as much possible the Profiling Sources interface
  29. // already defined by NT and HAL.
  30. //
  31. // - All processors in a multiprocessor system are running the microprocessor
  32. // at the same invariant clock speed.
  33. //
  34. // - All processors are configured with the same set of profiling counters.
  35. // XXTF - 04/01/2000 - This assumption is being re-worked and will disappear.
  36. //
  37. // - Profiling is based on the processor monitored events and if possible
  38. // on derived events.
  39. //
  40. // - A monitored event can only be enabled on one performance counter at a time.
  41. //
  42. //
  43. // IA64 performance counters defintions:
  44. // - event counters
  45. // - EARS
  46. // - BTBs
  47. // - ...
  48. //
  49. #include "ia64prof.h"
  50. #if defined(_MCKINLEY_)
  51. #include "mckinley.h"
  52. #else // Default IA64 - Merced
  53. #include "merced.h"
  54. #endif //
  55. extern ULONGLONG HalpITCFrequency;
  56. extern HALP_PROFILE_MAPPING HalpProfileMapping[];
  57. #define HalpDisactivateProfileSource( _ProfileSource ) ((_ProfileSource) = ProfileIA64Maximum)
  58. #define HalpIsProfileSourceActive( _ProfileSource ) ((_ProfileSource) != ProfileIA64Maximum)
  59. #define HalpIsProfileMappingInvalid( _ProfileMapping ) (!(_ProfileMapping) || ((_ProfileMapping)->Supported == FALSE))
  60. VOID
  61. HalpEnableProfileCounting (
  62. VOID
  63. )
  64. /*++
  65. Routine Description:
  66. This function enables the profile counters to increment.
  67. This function is the counterpart of HalpDisableProfileCounting().
  68. Arguments:
  69. None.
  70. Return Value:
  71. None.
  72. --*/
  73. {
  74. ULONGLONG Data, ClearStatusMask;
  75. //
  76. // Clear PMC0.fr - bit 0.
  77. // Clear PMCO,1,2,3 OverFlow Bits.
  78. //
  79. ClearStatusMask = 0xFFFFFFFFFFFFFF0E; // XXTF - FIXFIX - Merced specific.
  80. Data = HalpReadPerfMonCnfgReg0();
  81. Data &= ClearStatusMask;
  82. HalpWritePerfMonCnfgReg0(Data);
  83. return;
  84. } // HalpEnableProfileCounting()
  85. VOID
  86. HalpDisableProfileCounting (
  87. VOID
  88. )
  89. /*++
  90. Routine Description:
  91. This function disables the profile counters to increment.
  92. This function is the counterpart of HalpEnableProfileCounting().
  93. Arguments:
  94. None.
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. ULONGLONG Data, SetFreezeMask;
  100. SetFreezeMask = 0x1;
  101. Data = HalpReadPerfMonCnfgReg0();
  102. Data |= SetFreezeMask;
  103. HalpWritePerfMonCnfgReg0(Data);
  104. return;
  105. } // HalpDisableProfileCounting()
  106. VOID
  107. HalpSetInitialProfileState(
  108. VOID
  109. )
  110. /*++
  111. Routine Description:
  112. This function is called at HalInitSystem - phase 0 time to set
  113. the initial state of processor and profiling os subsystem with
  114. regards to the profiling functionality.
  115. Arguments:
  116. None.
  117. Return Value:
  118. None.
  119. --*/
  120. {
  121. // HalpProfilingRunning = 0;
  122. HalpDisableProfileCounting();
  123. return;
  124. } // HalpSetInitialProfileState()
  125. VOID
  126. HalpSetProfileCounterInterval (
  127. IN ULONG Counter,
  128. IN LONGLONG NextCount
  129. )
  130. /*++
  131. Routine Description:
  132. This function preloads the specified counter with a count value
  133. of 2^IMPL_BITS - NextCount.
  134. Arguments:
  135. Counter - Supplies the performance counter register number.
  136. NextCount - Supplies the value to preload in the monitor.
  137. An external interruption will be generated after NextCount.
  138. Return Value:
  139. None.
  140. Note:
  141. IMPL_BITS is defined by PAL_PERF_MON_INFO.PAL_WIDTH.
  142. ToDo:
  143. IMPL_BITS is hardcoded to 32.
  144. --*/
  145. {
  146. ULONGLONG Count;
  147. #define MAXIMUM_COUNT 4294967296 // 2 ** 32 for Merced. XXTF - FIXFIX - Merced specific.
  148. // if ( (Counter < 4) || (Counter > 7) ) return;
  149. if (NextCount > MAXIMUM_COUNT) {
  150. Count = 0;
  151. } else {
  152. Count = MAXIMUM_COUNT - NextCount;
  153. }
  154. HalpWritePerfMonDataReg( Counter, Count );
  155. #undef MAXIMUM_COUNT
  156. return;
  157. } // HalpSetProfileCounterInterval()
  158. VOID
  159. HalpSetProfileCounterPrivilegeLevelMask(
  160. IN ULONG Counter,
  161. IN ULONG Mask
  162. )
  163. /*++
  164. Routine Description:
  165. This function set the profile counter privilege level mask.
  166. Arguments:
  167. Counter - Supplies the performance counter register number.
  168. Mask - Supplies the privilege level mask to program the PMC with.
  169. Return Value:
  170. None.
  171. --*/
  172. {
  173. ULONGLONG data, plmMask;
  174. // if ( (Counter < 4) || (Counter > 7) ) return;
  175. plmMask = Mask & 0xF;
  176. data = HalpReadPerfMonCnfgReg( Counter );
  177. data &= ~0xF;
  178. data |= plmMask;
  179. HalpWritePerfMonCnfgReg( Counter, data );
  180. return;
  181. } // HalpSetProfileCounterPrivilegeLevelMask()
  182. VOID
  183. HalpEnableProfileCounterOverflowInterrupt (
  184. IN ULONG Counter
  185. )
  186. /*++
  187. Routine Description:
  188. This function enables the delivery of an overflow interrupt for
  189. the specified profile counter.
  190. Arguments:
  191. Counter - Supplies the performance counter register number.
  192. Return Value:
  193. None.
  194. --*/
  195. {
  196. ULONGLONG data, mask;
  197. // if ( (Counter < 4) || (Counter > 7) ) return;
  198. mask = 1<<5;
  199. data = HalpReadPerfMonCnfgReg( Counter );
  200. data |= mask;
  201. HalpWritePerfMonCnfgReg( Counter, data );
  202. return;
  203. } // HalpEnableProfileCounterOverflowInterrupt()
  204. VOID
  205. HalpDisableProfileCounterOverflowInterrupt (
  206. IN ULONG Counter
  207. )
  208. /*++
  209. Routine Description:
  210. This function disables the delivery of an overflow interrupt for
  211. the specified profile counter.
  212. Arguments:
  213. Counter - Supplies the performance counter register number.
  214. Return Value:
  215. None.
  216. --*/
  217. {
  218. ULONGLONG data, mask;
  219. // if ( (Counter < 4) || (Counter > 7) ) return;
  220. mask = 1<<5;
  221. data = HalpReadPerfMonCnfgReg( Counter );
  222. data &= ~mask;
  223. HalpWritePerfMonCnfgReg( Counter, data );
  224. return;
  225. } // HalpDisableProfileCounterOverflowInterrupt()
  226. VOID
  227. HalpEnableProfileCounterPrivilegeMonitor(
  228. IN ULONG Counter
  229. )
  230. /*++
  231. Routine Description:
  232. This function enables the profile counter as privileged monitor.
  233. Arguments:
  234. Counter - Supplies the performance counter register number.
  235. Return Value:
  236. None.
  237. --*/
  238. {
  239. ULONGLONG data, pm;
  240. // if ( (Counter < 4) || (Counter > 7) ) return;
  241. pm = 1<<6;
  242. data = HalpReadPerfMonCnfgReg( Counter );
  243. data |= pm;
  244. HalpWritePerfMonCnfgReg( Counter, data );
  245. return;
  246. } // HalpEnableProfileCounterPrivilegeMonitor()
  247. VOID
  248. HalpDisableProfileCounterPrivilegeMonitor(
  249. IN ULONG Counter
  250. )
  251. /*++
  252. Routine Description:
  253. This function disables the profile counter as privileged monitor.
  254. Arguments:
  255. Counter - Supplies the performance counter register number.
  256. Return Value:
  257. None.
  258. --*/
  259. {
  260. ULONGLONG data, pm;
  261. // if ( (Counter < 4) || (Counter > 7) ) return;
  262. pm = 1<<6;
  263. data = HalpReadPerfMonCnfgReg( Counter );
  264. data &= ~pm;
  265. HalpWritePerfMonCnfgReg( Counter, data );
  266. return;
  267. } // HalpDisableProfileCounterPrivilegeMonitor()
  268. VOID
  269. HalpSetProfileCounterEvent(
  270. IN ULONG Counter,
  271. IN ULONG Event
  272. )
  273. /*++
  274. Routine Description:
  275. The function specifies the monitor event for the profile counter.
  276. Arguments:
  277. Counter - Supplies the performance counter register number.
  278. Event - Supplies the monitor event code.
  279. Return Value:
  280. None.
  281. --*/
  282. {
  283. ULONGLONG data, es;
  284. // if ( (Counter < 4) || (Counter > 7) ) return;
  285. es = (Event & 0x7F) << 8;
  286. data = HalpReadPerfMonCnfgReg( Counter );
  287. data &= ~(0x7F << 8);
  288. data |= es;
  289. HalpWritePerfMonCnfgReg( Counter, data );
  290. return;
  291. } // HalpSetProfileCounterEvent()
  292. VOID
  293. HalpSetProfileCounterUmask(
  294. IN ULONG Counter,
  295. IN ULONG Umask
  296. )
  297. /*++
  298. Routine Description:
  299. This function sets the event specific umask value for the profile
  300. counter.
  301. Arguments:
  302. Counter - Supplies the performance counter register number.
  303. Umask - Supplies the event specific umask value.
  304. Return Value:
  305. None.
  306. --*/
  307. {
  308. ULONGLONG data, um;
  309. // if ( (Counter < 4) || (Counter > 7) ) return;
  310. um = (Umask & 0xF) << 16;
  311. data = HalpReadPerfMonCnfgReg( Counter );
  312. data &= ~(0xF << 16);
  313. data |= um;
  314. HalpWritePerfMonCnfgReg( Counter, data );
  315. return;
  316. } // HalpSetProfileCounterUmask()
  317. VOID
  318. HalpSetProfileCounterThreshold(
  319. IN ULONG Counter,
  320. IN ULONG Threshold
  321. )
  322. /*++
  323. Routine Description:
  324. This function sets the profile counter threshold.
  325. Arguments:
  326. Counter - Supplies the performance counter register number.
  327. Threshold - Supplies the desired threshold.
  328. This is related to multi-occurences events.
  329. Return Value:
  330. None.
  331. --*/
  332. {
  333. ULONGLONG data, reset, th;
  334. switch( Counter ) {
  335. case 4:
  336. case 5:
  337. Threshold &= 0x7;
  338. reset = ~(0x7 << 20);
  339. break;
  340. case 6:
  341. case 7:
  342. Threshold &= 0x3;
  343. reset = ~(0x3 << 20);
  344. break;
  345. default:
  346. return;
  347. }
  348. th = Threshold << 20;
  349. data = HalpReadPerfMonCnfgReg( Counter );
  350. data &= reset;
  351. data |= th;
  352. HalpWritePerfMonCnfgReg( Counter, data );
  353. return;
  354. } // HalpSetProfileCounterThreshold()
  355. VOID
  356. HalpSetProfileCounterInstructionSetMask(
  357. IN ULONG Counter,
  358. IN ULONG Mask
  359. )
  360. /*++
  361. Routine Description:
  362. This function sets the instruction set mask for the profile counter.
  363. Arguments:
  364. Counter - Supplies the performance counter register number.
  365. Mask - Supplies the instruction set mask.
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. ULONGLONG data, ismMask;
  371. // if ( (Counter < 4) || (Counter > 7) ) return;
  372. ismMask = (Mask & 0x3) << 24;
  373. data = HalpReadPerfMonCnfgReg( Counter );
  374. data &= ~(0x3 << 24);
  375. data |= ismMask;
  376. HalpWritePerfMonCnfgReg( Counter, data );
  377. return;
  378. } // HalpSetProfileCounterInstructionSetMask()
  379. VOID
  380. HalpSetProfileCounterConfiguration(
  381. IN ULONG Counter,
  382. IN ULONG PrivilegeMask,
  383. IN ULONG EnableOverflowInterrupt,
  384. IN ULONG EnablePrivilegeMonitor,
  385. IN ULONG Event,
  386. IN ULONG Umask,
  387. IN ULONG Threshold,
  388. IN ULONG InstructionSetMask
  389. )
  390. /*++
  391. Function Description:
  392. This function sets the profile counter with the specified parameters.
  393. Arguments:
  394. IN ULONG Counter -
  395. IN ULONG PrivilegeMask -
  396. IN ULONG EnableOverflowInterrupt -
  397. IN ULONG EnablePrivilegeMonitor -
  398. IN ULONG Event -
  399. IN ULONG Umask -
  400. IN ULONG Threshold -
  401. IN ULONG InstructionSetMask -
  402. Return Value:
  403. VOID
  404. Algorithm:
  405. ToBeSpecified
  406. In/Out Conditions:
  407. ToBeSpecified
  408. Globals Referenced:
  409. ToBeSpecified
  410. Exception Conditions:
  411. ToBeSpecified
  412. MP Conditions:
  413. ToBeSpecified
  414. Notes:
  415. This function is a kind of combo of the different profile counter APIs.
  416. It was created to provide speed.
  417. ToDo List:
  418. - Setting the threshold is not yet supported.
  419. Modification History:
  420. 3/16/2000 TF Initial version
  421. --*/
  422. {
  423. ULONGLONG data, plmMask, ismMask, es, um, th;
  424. // if ( (Counter < 4) || (Counter > 7) ) return;
  425. plmMask = (PrivilegeMask & 0xF);
  426. es = (Event & 0x7F) << 8;
  427. um = (Umask & 0xF) << 16;
  428. // XXTF - ToBeDone - Threshold not supported yet.
  429. ismMask = (InstructionSetMask & 0x3) << 24;
  430. data = HalpReadPerfMonCnfgReg( Counter );
  431. HalDebugPrint(( HAL_PROFILE, "HalpSetProfileCounterConfiguration: Counter = %ld Read = 0x%I64x\n", Counter, data ));
  432. data &= ~( (0x3 << 24) | (0xF << 16) | (0x7F << 8) | 0xF );
  433. data |= ( plmMask | es | um | ismMask );
  434. data = EnableOverflowInterrupt ? (data | (1<<5)) : (data & ~(1<<5));
  435. data = EnablePrivilegeMonitor ? (data | (1<<6)) : (data & ~(1<<6));
  436. HalpWritePerfMonCnfgReg( Counter, data );
  437. HalDebugPrint(( HAL_PROFILE, "HalpSetProfileCounterConfiguration: Counter = %ld Written = 0x%I64x\n", Counter, data ));
  438. return;
  439. } // HalpSetProfileCounterConfiguration()
  440. NTSTATUS
  441. HalpProgramProfileMapping(
  442. PHALP_PROFILE_MAPPING ProfileMapping,
  443. KPROFILE_SOURCE ProfileSource
  444. )
  445. /*++
  446. Routine Description:
  447. This function enables the profiling configuration for the event defined by the
  448. specified Profile Mapping entry.
  449. Arguments:
  450. ProfileMapping - Supplies the Profile Mapping entry.
  451. ProfileSource - Supplies the Profile Source corresponding to the Profile Mapping entry.
  452. Return Value:
  453. STATUS_SUCCESS -
  454. STATUS_INVALID_PARAMETER -
  455. STATUS_UNSUCESSFUL -
  456. --*/
  457. {
  458. NTSTATUS status;
  459. ULONG sourceMask;
  460. if ( ! ProfileMapping ) {
  461. return STATUS_INVALID_PARAMETER;
  462. }
  463. // XXTF - ToBeDone - Derived Event
  464. sourceMask = ProfileMapping->ProfileSourceMask;
  465. if ( (sourceMask & PMCD_MASK_4) && !HalpIsProfileSourceActive( HalpProfileSource4 ) ) {
  466. HalpSetProfileCounterConfiguration( 4,
  467. PMC_PLM_ALL,
  468. PMC_ENABLE_OVERFLOW_INTERRUPT,
  469. PMC_ENABLE_PRIVILEGE_MONITOR,
  470. ProfileMapping->Event,
  471. 0, // Umask
  472. 0, // Threshold
  473. PMC_ISM_ALL
  474. );
  475. HalpSetProfileCounterInterval( 4, ProfileMapping->Interval );
  476. HalpProfileSource4 = ProfileSource;
  477. return STATUS_SUCCESS;
  478. }
  479. if ( (sourceMask & PMCD_MASK_5) && !HalpIsProfileSourceActive( HalpProfileSource5 ) ) {
  480. HalpSetProfileCounterConfiguration( 5,
  481. PMC_PLM_ALL,
  482. PMC_ENABLE_OVERFLOW_INTERRUPT,
  483. PMC_ENABLE_PRIVILEGE_MONITOR,
  484. ProfileMapping->Event,
  485. 0, // Umask
  486. 0, // Threshold
  487. PMC_ISM_ALL
  488. );
  489. HalpSetProfileCounterInterval( 5, ProfileMapping->Interval );
  490. HalpProfileSource5 = ProfileSource;
  491. return STATUS_SUCCESS;
  492. }
  493. if ( (sourceMask & PMCD_MASK_6) && !HalpIsProfileSourceActive( HalpProfileSource6 ) ) {
  494. HalpSetProfileCounterConfiguration( 6,
  495. PMC_PLM_ALL,
  496. PMC_ENABLE_OVERFLOW_INTERRUPT,
  497. PMC_ENABLE_PRIVILEGE_MONITOR,
  498. ProfileMapping->Event,
  499. 0, // Umask
  500. 0, // Threshold
  501. PMC_ISM_ALL
  502. );
  503. HalpSetProfileCounterInterval( 6, ProfileMapping->Interval );
  504. HalpProfileSource6 = ProfileSource;
  505. return STATUS_SUCCESS;
  506. }
  507. if ( (sourceMask & PMCD_MASK_7) && !HalpIsProfileSourceActive( HalpProfileSource7 ) ) {
  508. HalpSetProfileCounterConfiguration( 7,
  509. PMC_PLM_ALL,
  510. PMC_ENABLE_OVERFLOW_INTERRUPT,
  511. PMC_ENABLE_PRIVILEGE_MONITOR,
  512. ProfileMapping->Event,
  513. 0, // Umask
  514. 0, // Threshold
  515. PMC_ISM_ALL
  516. );
  517. HalpSetProfileCounterInterval( 7, ProfileMapping->Interval );
  518. HalpProfileSource7 = ProfileSource;
  519. return STATUS_SUCCESS;
  520. }
  521. return STATUS_UNSUCCESSFUL;
  522. } // HalpProgramProfileMapping()
  523. ULONG_PTR
  524. HalpSetProfileInterruptHandler(
  525. IN ULONG_PTR ProfileInterruptHandler
  526. )
  527. /*++
  528. Routine Description:
  529. This function registers a per-processor Profiling Interrupt Handler.
  530. Arguments:
  531. ProfileInterruptHandler - Interrupt Handler.
  532. Return Value:
  533. (ULONG_PTR)STATUS_SUCCESS - Successful registration.
  534. (ULONG_PTR)STATUS_ALREADY_COMMITTED - Cannot register an handler if profiling events are running.
  535. (ULONG_PTR)STATUS_PORT_ALREADY_SET - An Profiling Interrupt Handler was already registred - not imposed currently.
  536. Note:
  537. IT IS THE RESPONSIBILITY OF THE CALLER OF THIS ROUTINE TO ENSURE
  538. THAT NO PAGE FAULTS WILL OCCUR DURING EXECUTION OF THE PROVIDED
  539. FUNCTION OR ACCESS TO THE PROVIDED CONTEXT.
  540. A MINIMUM OF FUNCTION POINTER CHECKING WAS DONE IN HalSetSystemInformation PROCESSING.
  541. --*/
  542. {
  543. //
  544. // If profiling is already running, we do not allow the handler registration.
  545. //
  546. // This imposes that:
  547. //
  548. // - if the default HAL profiling is running or a profiling with a registered interrupt
  549. // handler is running, we cannot register an interrupt handler.
  550. // In the last case, all the profiling events have to be stopped before a possible
  551. // registration.
  552. //
  553. // It should be also noticed that there is no ownership of profiling monitors implemented.
  554. // Meaning that if profiling is started, the registred handler will get the interrupts
  555. // generated by ALL the running monitor events if they are programmed to generate interrupts.
  556. //
  557. if ( HalpProfilingRunning ) {
  558. HalDebugPrint(( HAL_PROFILE, "HalpSetProfileInterruptHandler: Profiling already running\n" ));
  559. return((ULONG_PTR)(ULONG)(STATUS_ALREADY_COMMITTED));
  560. }
  561. #if 0
  562. //
  563. // Thierry - 03/2000. ToBeVerified.
  564. //
  565. // In case, no profiling was started, there is currently no restriction in registering
  566. // another handler if one was already registered.
  567. //
  568. if ( HalpProfillingInterruptHandler ) {
  569. return((ULONG_PTR)(ULONG)(STATUS_PORT_ALREADY_SET));
  570. }
  571. #endif // 0
  572. HalpProfilingInterruptHandler = (ULONGLONG)ProfileInterruptHandler;
  573. return((ULONG_PTR)(ULONG)(STATUS_SUCCESS));
  574. } // HalpSetProfileInterruptHandler()
  575. VOID
  576. HalpProfileInterrupt(
  577. IN PKINTERRUPT_ROUTINE Interrupt,
  578. IN PKTRAP_FRAME TrapFrame
  579. )
  580. /*++
  581. Routine Description:
  582. Default PROFILE_VECTOR Interrupt Handler.
  583. This function is executed as the result of an interrupt from the
  584. internal microprocessor performance counters. The interrupt
  585. may be used to signal the completion of a profile event.
  586. If profiling is current active, the function determines if the
  587. profile interval has expired and if so dispatches to the standard
  588. system routine to update the system profile time. If profiling
  589. is not active then returns.
  590. Arguments:
  591. TrapFrame - Trap frame address.
  592. Return Value:
  593. None.
  594. --*/
  595. {
  596. //
  597. // Call registered per-processor Profiling Interrupt handler if it exists.
  598. // We will return immediately before doing any default profiling interrupt handling.
  599. //
  600. // XXTF - ToBeVerified - This functionality has to be verified before
  601. // final check-in.
  602. //
  603. if ( HalpProfilingInterruptHandler ) {
  604. (*((PHAL_PROFILE_INTERRUPT_HANDLER)HalpProfilingInterruptHandler))( TrapFrame );
  605. return;
  606. }
  607. //
  608. // Handle interrupt if profiling is enabled.
  609. //
  610. if ( HalpProfilingRunning ) {
  611. //
  612. // Process every PMC/PMD pair overflow.
  613. //
  614. // XXTF - FIXFIX - Merced specific.
  615. UCHAR pmc0, overflow;
  616. ULONG source;
  617. HalpProfilingInterrupts++;
  618. pmc0 = (UCHAR)HalpReadPerfMonCnfgReg0();
  619. ASSERTMSG( "HAL!HalpProfileInterrupt PMC0 freeze bit is not set!\n", pmc0 & 0x1 );
  620. overflow = pmc0 & 0xF0;
  621. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", overflow );
  622. if ( overflow & (1<<4) ) {
  623. source = HalpProfileSource4; // XXTF - IfFaster - Coud used pmc.es
  624. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
  625. KeProfileInterruptWithSource( TrapFrame, source );
  626. HalpSetProfileCounterInterval( 4, HalpProfileMapping[source].Interval );
  627. // XXTF - IfFaster - HalpWritePerfMonDataReg( 4, HalpProfileMapping[source].Interval );
  628. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 4, *PCRProfileCnfg4Reload );
  629. }
  630. if ( overflow & (1<<5) ) {
  631. source = HalpProfileSource5; // XXTF - IfFaster - Coud used pmc.es
  632. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
  633. KeProfileInterruptWithSource( TrapFrame, source );
  634. HalpSetProfileCounterInterval( 5, HalpProfileMapping[source].Interval );
  635. // XXTF - IfFaster - HalpWritePerfMonDataReg( 5, HalpProfileMapping[source].Interval );
  636. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 5, *PCRProfileCnfg5Reload );
  637. }
  638. if ( overflow & (1<<6) ) {
  639. source = HalpProfileSource6; // XXTF - IfFaster - Coud used pmc.es
  640. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
  641. KeProfileInterruptWithSource( TrapFrame, source );
  642. HalpSetProfileCounterInterval( 6, HalpProfileMapping[source].Interval );
  643. // XXTF - IfFaster - HalpWritePerfMonDataReg( 6, HalpProfileMapping[source].Interval );
  644. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 6, *PCRProfileCnfg6Reload );
  645. }
  646. if ( overflow & (1<<7) ) {
  647. source = HalpProfileSource7; // XXTF - IfFaster - Coud used pmc.es
  648. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
  649. KeProfileInterruptWithSource( TrapFrame, source );
  650. HalpSetProfileCounterInterval( 7, HalpProfileMapping[source].Interval );
  651. // XXTF - IfFaster - HalpWritePerfMonDataReg( 6, HalpProfileMapping[source].Interval );
  652. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 7, *PCRProfileCnfg7Reload );
  653. }
  654. //
  655. // Clear pmc0.fr and overflow bits.
  656. //
  657. HalpEnableProfileCounting();
  658. }
  659. else {
  660. HalpProfilingInterruptsWithoutProfiling++;
  661. }
  662. return;
  663. } // HalpProfileInterrupt()
  664. PHALP_PROFILE_MAPPING
  665. HalpGetProfileMapping(
  666. IN KPROFILE_SOURCE Source
  667. )
  668. /*++
  669. Routine Description:
  670. Given a profile source, returns whether or not that source is
  671. supported.
  672. Arguments:
  673. Source - Supplies the profile source
  674. Return Value:
  675. TRUE - Profile source is supported
  676. FALSE - Profile source is not supported
  677. --*/
  678. {
  679. if ( Source > ProfileIA64Maximum /* = (sizeof(HalpProfileMapping)/sizeof(HalpProfileMapping[0])) */ )
  680. {
  681. return NULL;
  682. }
  683. return(&HalpProfileMapping[Source]);
  684. } // HalpGetProfileMapping()
  685. BOOLEAN
  686. HalQueryProfileInterval(
  687. IN KPROFILE_SOURCE Source
  688. )
  689. /*++
  690. Routine Description:
  691. Given a profile source, returns whether or not that source is
  692. supported.
  693. Arguments:
  694. Source - Supplies the profile source
  695. Return Value:
  696. TRUE - Profile source is supported
  697. FALSE - Profile source is not supported
  698. --*/
  699. {
  700. PHALP_PROFILE_MAPPING profileMapping;
  701. profileMapping = HalpGetProfileMapping( Source );
  702. if ( !profileMapping ) {
  703. return(FALSE);
  704. }
  705. return( profileMapping->Supported );
  706. } // HalQueryProfileInterval()
  707. NTSTATUS
  708. HalSetProfileSourceInterval(
  709. IN KPROFILE_SOURCE ProfileSource,
  710. IN OUT ULONG_PTR *Interval
  711. )
  712. /*++
  713. Routine Description:
  714. Sets the profile interval for a specified profile source
  715. Arguments:
  716. ProfileSource - Supplies the profile source
  717. Interval - Supplies the specified profile interval
  718. Returns the actual profile interval
  719. - if ProfileSource is ProfileTime, Interval is in 100ns units.
  720. Return Value:
  721. NTSTATUS
  722. --*/
  723. {
  724. ULONGLONG countEvents;
  725. PHALP_PROFILE_MAPPING profileMapping;
  726. profileMapping = HalpGetProfileMapping(ProfileSource);
  727. if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
  728. return(STATUS_NOT_IMPLEMENTED);
  729. }
  730. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: ProfileSource = %ld IN *Interval = 0x%Ix\n", ProfileSource, *Interval ));
  731. if ( ProfileSource == ProfileTime ) {
  732. //
  733. // Convert the clock tick period (in 100ns units) into a cycle count period
  734. //
  735. countEvents = (ULONGLONG)(*Interval * HalpITCTicksPer100ns);
  736. }
  737. else {
  738. countEvents = (ULONGLONG)*Interval;
  739. }
  740. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: countEvent = 0x%I64x\n", countEvents ));
  741. //
  742. // Check to see if the desired Interval is reasonable, if not adjust it.
  743. //
  744. if ( countEvents > profileMapping->MaxInterval ) {
  745. countEvents = profileMapping->MaxInterval;
  746. }
  747. else if ( countEvents < profileMapping->MinInterval ) {
  748. countEvents = profileMapping->MinInterval;
  749. }
  750. profileMapping->Interval = countEvents;
  751. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: CurrentInterval = 0x%I64x\n", profileMapping->Interval ));
  752. if ( ProfileSource == ProfileTime ) {
  753. ULONGLONG tempInterval;
  754. //
  755. // Convert cycle count back into 100ns clock ticks
  756. //
  757. tempInterval = (ULONGLONG)(countEvents / HalpITCTicksPer100ns);
  758. #if 0
  759. if ( tempInterval < 1 ) {
  760. tempInterval = 1;
  761. }
  762. #endif
  763. *Interval = (ULONG_PTR)tempInterval;
  764. }
  765. else {
  766. *Interval = (ULONG_PTR)countEvents;
  767. }
  768. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: ProfileSource = %ld OUT *Interval = 0x%Ix\n", ProfileSource, *Interval ));
  769. return STATUS_SUCCESS;
  770. } // HalSetProfileSourceInterval()
  771. ULONG_PTR
  772. HalSetProfileInterval (
  773. IN ULONG_PTR Interval
  774. )
  775. /*++
  776. Routine Description:
  777. This routine sets the ProfileTime source interrupt interval.
  778. Arguments:
  779. Interval - Supplies the desired profile interval in 100ns units.
  780. Return Value:
  781. The actual profile interval.
  782. --*/
  783. {
  784. ULONG_PTR NewInterval;
  785. NewInterval = Interval;
  786. HalSetProfileSourceInterval(ProfileTime, &NewInterval);
  787. return(NewInterval);
  788. } // HalSetProfileInterval()
  789. VOID
  790. HalStartProfileInterrupt (
  791. KPROFILE_SOURCE ProfileSource
  792. )
  793. /*++
  794. Routine Description:
  795. This routine turns on the profile interrupt.
  796. N.B. This routine must be called at PROFILE_LEVEL while holding the profile lock if MP.
  797. Arguments:
  798. None.
  799. Return Value:
  800. None.
  801. --*/
  802. {
  803. BOOLEAN disabledProfileCounting;
  804. NTSTATUS status;
  805. PHALP_PROFILE_MAPPING profileMapping;
  806. //
  807. // Get the Hal profile mapping entry associated with the specified source.
  808. //
  809. profileMapping = HalpGetProfileMapping( ProfileSource );
  810. if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
  811. HalDebugPrint(( HAL_PROFILE, "HalStartProfileInterrupt: invalid source = %ld\n", ProfileSource ));
  812. return;
  813. }
  814. //
  815. // Disable the profile counting if enabled.
  816. //
  817. disabledProfileCounting = FALSE;
  818. if ( HalpProfilingRunning && !(HalpReadPerfMonCnfgReg0() & 0x1) ) {
  819. HalpDisableProfileCounting();
  820. disabledProfileCounting = TRUE;
  821. }
  822. //
  823. // Obtain and initialize an available PMC register that supports this event.
  824. // We may enable more than one event.
  825. // If the initialization failed, we return immediately.
  826. //
  827. // XXTF - FIXFIX - is there a way to
  828. // * notify the caller for the failure and the reason of the failure. or
  829. // * modify the API. or
  830. // * define a new API.
  831. //
  832. status = HalpProgramProfileMapping( profileMapping, ProfileSource );
  833. if ( !NT_SUCCESS(status) ) {
  834. HalDebugPrint(( HAL_PROFILE, "HalStartProfileInterrupt: HalpProgramProfileMapping failed.\n" ));
  835. if ( disabledProfileCounting ) {
  836. HalpEnableProfileCounting();
  837. }
  838. return;
  839. }
  840. //
  841. // Notify the profiling as active.
  842. // before enabling the selected pmc overflow interrupt and unfreezing the counters.
  843. //
  844. HalpProfilingRunning++;
  845. HalpEnableProfileCounting();
  846. return;
  847. } // HalStartProfileInterrupt()
  848. VOID
  849. HalStopProfileInterrupt (
  850. KPROFILE_SOURCE ProfileSource
  851. )
  852. /*++
  853. Routine Description:
  854. This routine turns off the profile interrupt.
  855. N.B. This routine must be called at PROFILE_LEVEL while holding the
  856. profile lock.
  857. Arguments:
  858. ProfileSource - Supplies the Profile Source to stop.
  859. Return Value:
  860. None.
  861. --*/
  862. {
  863. PHALP_PROFILE_MAPPING profileMapping;
  864. //
  865. // Get the Hal profile mapping entry associated with the specified profile source.
  866. //
  867. profileMapping = HalpGetProfileMapping( ProfileSource );
  868. if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
  869. HalDebugPrint(( HAL_PROFILE, "HalStopProfileInterrupt: invalid source = %ld\n", ProfileSource ));
  870. return;
  871. }
  872. //
  873. // Validate the Profile Source as active.
  874. //
  875. if ( HalpProfileSource4 == ProfileSource ) {
  876. // XXTF - FIXFIX - Derived Event - ToBeDone
  877. HalpSetProfileCounterConfiguration( 4,
  878. PMC_PLM_NONE,
  879. PMC_DISABLE_OVERFLOW_INTERRUPT,
  880. PMC_DISABLE_PRIVILEGE_MONITOR,
  881. 0, // Event
  882. 0, // Umask
  883. 0, // Threshold
  884. PMC_ISM_NONE
  885. );
  886. HalpSetProfileCounterInterval( 4, 0 );
  887. HalpDisactivateProfileSource( HalpProfileSource4 );
  888. HalpProfilingRunning--;
  889. }
  890. else if ( HalpProfileSource5 == ProfileSource ) {
  891. // XXTF - FIXFIX - Derived Event - ToBeDone
  892. HalpSetProfileCounterConfiguration( 5,
  893. PMC_PLM_NONE,
  894. PMC_DISABLE_OVERFLOW_INTERRUPT,
  895. PMC_DISABLE_PRIVILEGE_MONITOR,
  896. 0, // Event
  897. 0, // Umask
  898. 0, // Threshold
  899. PMC_ISM_NONE
  900. );
  901. HalpSetProfileCounterInterval( 5, 0 );
  902. HalpDisactivateProfileSource( HalpProfileSource5 );
  903. HalpProfilingRunning--;
  904. }
  905. else if ( HalpProfileSource6 == ProfileSource ) {
  906. // XXTF - FIXFIX - Derived Event - ToBeDone
  907. HalpSetProfileCounterConfiguration( 6,
  908. PMC_PLM_NONE,
  909. PMC_DISABLE_OVERFLOW_INTERRUPT,
  910. PMC_DISABLE_PRIVILEGE_MONITOR,
  911. 0, // Event
  912. 0, // Umask
  913. 0, // Threshold
  914. PMC_ISM_NONE
  915. );
  916. HalpSetProfileCounterInterval( 6, 0 );
  917. HalpDisactivateProfileSource( HalpProfileSource6);
  918. HalpProfilingRunning--;
  919. }
  920. else if ( HalpProfileSource7 == ProfileSource ) {
  921. // XXTF - FIXFIX - Derived Event - ToBeDone
  922. HalpSetProfileCounterConfiguration( 7,
  923. PMC_PLM_NONE,
  924. PMC_DISABLE_OVERFLOW_INTERRUPT,
  925. PMC_DISABLE_PRIVILEGE_MONITOR,
  926. 0, // Event
  927. 0, // Umask
  928. 0, // Threshold
  929. PMC_ISM_NONE
  930. );
  931. HalpSetProfileCounterInterval( 7, 0 );
  932. HalpDisactivateProfileSource( HalpProfileSource7 );
  933. HalpProfilingRunning--;
  934. }
  935. return;
  936. } // HalStopProfileInterrupt()
  937. VOID
  938. HalpResetProcessorDependentPerfMonCnfgRegs(
  939. ULONGLONG DefaultValue
  940. )
  941. /*++
  942. Routine Description:
  943. This routine initializes the processor dependent performance configuration
  944. registers.
  945. Arguments:
  946. DefaultValue - default value used to initialize IA64 generic PMCs.
  947. Return Value:
  948. None.
  949. --*/
  950. {
  951. // XXTF - 02/08/2000
  952. // For now, there is no initialization for processor dependent performance
  953. // configuration registers.
  954. return;
  955. } // HalpResetProcessorDependentPerfMonCnfgRegs()
  956. VOID
  957. HalpResetPerfMonCnfgRegs(
  958. VOID
  959. )
  960. /*++
  961. Routine Description:
  962. This routine initializes the IA64 architected performance configuration
  963. registers and calls the micro-architecture specific initialization.
  964. Arguments:
  965. None.
  966. Return Value:
  967. None.
  968. --*/
  969. {
  970. ULONG pmc;
  971. ULONGLONG value;
  972. //
  973. // PMC Reset value:
  974. // Reg. Field Bits
  975. // PMC* .plm - 3: 0 - Privilege Mask - 0 (Disable Counter)
  976. // PMC* .ev - 4 - External Visibility - 0 (Disabled)
  977. // PMC* .oi - 5 - Overflow Interrupt - 0 (Disabled)
  978. // PMC* .pm - 6 - Privilege Monitor - 0 (user monitor)
  979. // PMC* .ig - 7 - Ignored
  980. // PMC* .es - 14: 8 - Event Select - 0 (XXTF - Warning - 0x0 = Real Event)
  981. // PMC* .ig - 15 - Ignored
  982. // PMC* .umask - 19:16 - Unit Mask - 0 (event specific. ok for .es=0)
  983. // PMC4,5 .threshold - 22:20 - Threshold - 0 (multi-occurence events threshold)
  984. // PMC4,5 .ig - 23 - Ignored
  985. // PMC6,7 .threshold - 21:20 - Threshold - 0 (multi-occurence events threshold)
  986. // PMC6,7 .ig - 23:22 - Ignored
  987. // PMC* .ism - 25:24 - Instruction Set Mask - 0 (IA64 & IA32 sets - 11:disables monitoring)
  988. // PMC* .ig - 63:26 - Ignored
  989. // -----
  990. // PMC_RESET
  991. #define PMC_RESET 0ui64
  992. value = PMC_RESET;
  993. for ( pmc = 4; pmc < 8; pmc++ ) {
  994. HalpWritePerfMonCnfgReg( pmc, value );
  995. }
  996. HalpResetProcessorDependentPerfMonCnfgRegs( value );
  997. #undef PMC_RESET
  998. return;
  999. } // HalpResetPerfMonCnfgRegs()
  1000. VOID
  1001. HalpInitializeProfiling (
  1002. ULONG Number
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine is called during initialization to initialize profiling
  1007. for each processor in the system.
  1008. Called from HalInitSystem at phase 1 on every processor.
  1009. Arguments:
  1010. Number - Supplies the processor number.
  1011. Return Value:
  1012. None.
  1013. --*/
  1014. {
  1015. //
  1016. // If BSP processor, initialize the ProfileTime Interval entries.
  1017. //
  1018. // Assumes HalpITCTicksPer100ns has been initialized.
  1019. if ( Number == 0 ) {
  1020. ULONGLONG interval;
  1021. ULONGLONG count;
  1022. PHALP_PROFILE_MAPPING profile;
  1023. profile = &HalpProfileMapping[ProfileTime];
  1024. interval = DEFAULT_PROFILE_INTERVAL;
  1025. count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
  1026. profile->DefInterval = count;
  1027. interval = MAXIMUM_PROFILE_INTERVAL;
  1028. count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
  1029. profile->MaxInterval = count;
  1030. interval = MINIMUM_PROFILE_INTERVAL;
  1031. count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
  1032. profile->MinInterval = count;
  1033. }
  1034. //
  1035. // ToBeDone - checkpoint for default processor.PSR fields for
  1036. // performance monitoring.
  1037. //
  1038. //
  1039. // Resets the processor performance configuration registers.
  1040. //
  1041. HalpResetPerfMonCnfgRegs();
  1042. //
  1043. // Initialization of the Per processor profiling data.
  1044. //
  1045. HalpProfilingRunning = 0;
  1046. HalpDisactivateProfileSource( HalpProfileSource4 );
  1047. HalpDisactivateProfileSource( HalpProfileSource5 );
  1048. HalpDisactivateProfileSource( HalpProfileSource6 );
  1049. HalpDisactivateProfileSource( HalpProfileSource7 );
  1050. //
  1051. // XXTF 02/08/2000:
  1052. // Different performance vectors are considered:
  1053. // - Profiling (default) -> PROFILE_VECTOR
  1054. // - Tracing -> PERF_VECTOR [PMUTRACE_VECTOR]
  1055. //
  1056. // Set default Performance vector to Profiling.
  1057. //
  1058. ASSERTMSG( "HAL!HalpInitializeProfiler PROFILE_VECTOR handler != HalpProfileInterrupt\n",
  1059. PCR->InterruptRoutine[PROFILE_VECTOR] == (PKINTERRUPT_ROUTINE)HalpProfileInterrupt );
  1060. HalpWritePerfMonVectorReg( PROFILE_VECTOR );
  1061. return;
  1062. } // HalpInitializeProfiler()
  1063. NTSTATUS
  1064. HalpProfileSourceInformation (
  1065. OUT PVOID Buffer,
  1066. IN ULONG BufferLength,
  1067. OUT PULONG ReturnedLength
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. Returns the HAL_PROFILE_SOURCE_INFORMATION or
  1072. HAL_PROFILE_SOURCE_INFORMATION_EX for this processor.
  1073. Arguments:
  1074. Buffer - output buffer
  1075. BufferLength - length of buffer on input
  1076. ReturnedLength - The length of data returned
  1077. Return Value:
  1078. STATUS_SUCCESS
  1079. STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
  1080. currently needed.
  1081. --*/
  1082. {
  1083. PHALP_PROFILE_MAPPING profileMapping;
  1084. NTSTATUS status;
  1085. if ( (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) &&
  1086. (BufferLength < sizeof(HAL_PROFILE_SOURCE_INFORMATION_EX)) )
  1087. {
  1088. status = STATUS_INFO_LENGTH_MISMATCH;
  1089. return status;
  1090. }
  1091. profileMapping = HalpGetProfileMapping(((PHAL_PROFILE_SOURCE_INFORMATION)Buffer)->Source);
  1092. //
  1093. // return a different status error if the source is not supported or
  1094. // the source is not a valid
  1095. //
  1096. if ( profileMapping == NULL ) {
  1097. status = STATUS_INVALID_PARAMETER;
  1098. return status;
  1099. }
  1100. if ( BufferLength == sizeof(HAL_PROFILE_SOURCE_INFORMATION) ) {
  1101. PHAL_PROFILE_SOURCE_INFORMATION sourceInfo;
  1102. //
  1103. // HAL_PROFILE_SOURCE_INFORMATION buffer.
  1104. //
  1105. sourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
  1106. sourceInfo->Supported = profileMapping->Supported;
  1107. if ( sourceInfo->Supported ) {
  1108. //
  1109. // For ProfileTime, we convert cycle count back into 100ns clock ticks.
  1110. //
  1111. if ( profileMapping->ProfileSource == ProfileTime ) {
  1112. sourceInfo->Interval = (ULONG) (profileMapping->Interval / HalpITCTicksPer100ns);
  1113. }
  1114. else {
  1115. sourceInfo->Interval = (ULONG) profileMapping->Interval;
  1116. }
  1117. }
  1118. if ( ReturnedLength ) {
  1119. *ReturnedLength = sizeof(HAL_PROFILE_SOURCE_INFORMATION);
  1120. }
  1121. }
  1122. else {
  1123. PHAL_PROFILE_SOURCE_INFORMATION_EX sourceInfoEx;
  1124. //
  1125. // HAL_PROFILE_SOURCE_INFORMATION_EX buffer.
  1126. //
  1127. sourceInfoEx = (PHAL_PROFILE_SOURCE_INFORMATION_EX)Buffer;
  1128. sourceInfoEx->Supported = profileMapping->Supported;
  1129. if ( sourceInfoEx->Supported ) {
  1130. //
  1131. // For ProfileTime, we convert cycle count back into 100ns clock ticks.
  1132. //
  1133. if ( profileMapping->ProfileSource == ProfileTime ) {
  1134. sourceInfoEx->Interval = (ULONG_PTR) (profileMapping->Interval / HalpITCTicksPer100ns);
  1135. }
  1136. else {
  1137. sourceInfoEx->Interval = (ULONG_PTR) profileMapping->Interval;
  1138. }
  1139. sourceInfoEx->DefInterval = (ULONG_PTR) profileMapping->DefInterval;
  1140. sourceInfoEx->MaxInterval = (ULONG_PTR) profileMapping->MaxInterval;
  1141. sourceInfoEx->MinInterval = (ULONG_PTR) profileMapping->MinInterval;
  1142. }
  1143. if ( ReturnedLength ) {
  1144. *ReturnedLength = sizeof(HAL_PROFILE_SOURCE_INFORMATION_EX);
  1145. }
  1146. }
  1147. return STATUS_SUCCESS;
  1148. } // HalpProfileSourceInformation()