Leaked source code of windows server 2003
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.

2048 lines
56 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. 02-2002: Thierry for McKinley support.
  23. --*/
  24. #include "halp.h"
  25. //
  26. // Assumptions for the current implementation - 02/08/2000 :
  27. // These assumptions will be re-evaluated and worked out if required.
  28. //
  29. // - Respect and satisfy as much possible the Profiling Sources interface
  30. // already defined by NT and HAL.
  31. //
  32. // - All processors in a multiprocessor system are running the microprocessor
  33. // at the same invariant clock speed.
  34. //
  35. // - All processors are configured with the same set of profiling counters.
  36. // XXTF - 04/01/2000 - This assumption is being re-worked and will disappear.
  37. //
  38. // - Profiling is based on the processor monitored events and if possible
  39. // on derived events.
  40. //
  41. // - A monitored event can only be enabled on one performance counter at a time.
  42. //
  43. //
  44. // IA64 performance counters defintions:
  45. // - event counters
  46. // - EARS
  47. // - BTBs
  48. // - ...
  49. //
  50. #include "ia64prof.h"
  51. #include "merced.h"
  52. #include "mckinley.h"
  53. //
  54. // HALIA64 Processor PMC Reset definitions:
  55. //
  56. //
  57. // PMC Reset value:
  58. // Reg. Field Bits
  59. // PMC* .plm - 3: 0 - Privilege Mask - 0 (Disable Counter)
  60. // PMC* .ev - 4 - External Visibility - 0 (Disabled)
  61. // PMC* .oi - 5 - Overflow Interrupt - 0 (Disabled)
  62. // PMC* .pm - 6 - Privilege Monitor - 0 (user monitor)
  63. // PMC* .ig - 7 - Ignored - 0
  64. // PMC* .es - 14: 8 - Event Select - 0 (Warning - 0x0 = Real Event)
  65. // PMC* .ig - 15 - Ignored - 0
  66. // PMC* .umask - 19:16 - Unit Mask - 0 (event specific. ok for .es=0)
  67. // PMC4,5 .threshold - 22:20 - Threshold - 0 (multi-occurence events threshold)
  68. // PMC4 .pmu - 23 - enable PMU - 1
  69. // PMC5 .ig - 23 - Ignored - 0
  70. // PMC6,7 .threshold - 21:20 - Threshold - 0 (multi-occurence events threshold)
  71. // PMC6,7 .ig - 23:22 - Ignored - 0
  72. // PMC* .ism - 25:24 - Instruction Set Mask - 0 (IA64 & IA32 sets - 11:disables monitoring)
  73. // PMC* .ig - 63:26 - Ignored
  74. // ===
  75. // HALP_PMC_RESET
  76. // HALP_PMC4_RESET
  77. //
  78. #define HALP_PMC_RESET 0x0000000000000000ui64
  79. #define HALP_PMC4_RESET 0x0000000000800000ui64 // PMC4.pmu{bit23} enabled.
  80. //
  81. // HALIA64 Processor PMC Clear Status Masks:
  82. //
  83. // Note - FIXFIX - Merced, McKinley specific definitions.
  84. //
  85. #define HALP_PMC0_CLEAR_STATUS_MASK 0xFFFFFFFFFFFFFF0Eui64
  86. #define HALP_PMC1_CLEAR_STATUS_MASK 0xFFFFFFFFFFFFFFFFui64
  87. #define HALP_PMC2_CLEAR_STATUS_MASK 0xFFFFFFFFFFFFFFFFui64
  88. #define HALP_PMC3_CLEAR_STATUS_MASK 0xFFFFFFFFFFFFFFFFui64
  89. ////////////////
  90. //
  91. // HALIA64 Profile IA64 MicroArchitecture NameSpace
  92. //
  93. extern HALP_PROFILE_MAPPING HalpMercedProfileMapping[];
  94. extern HALP_PROFILE_MAPPING HalpMcKinleyProfileMapping[];
  95. #define HalpMercedPerfMonDataMaximumCount ((((ULONGLONG)1)<<32)-1)
  96. #define HalpMcKinleyPerfMonDataMaximumCount ((((ULONGLONG)1)<<47)-1)
  97. typedef enum _HALP_PROFILE_MICROARCHITECTURE {
  98. HALP_PROFILE_IA64_MERCED = 0x0,
  99. HALP_PROFILE_IA64_MCKINLEY = 0x1,
  100. } HALP_PROFILE_MICROARCHITECTURE;
  101. struct _HALP_PROFILE_INFO {
  102. HALP_PROFILE_MICROARCHITECTURE ProfileMicroArchitecture;
  103. BOOLEAN ProfilePerfMonCnfg0FreezeBitInterrupt;
  104. BOOLEAN ProfileSpare0;
  105. USHORT ProfilePerfMonGenericPairs;
  106. HALP_PROFILE_MAPPING *ProfileMapping;
  107. ULONG ProfileSourceMaximum;
  108. ULONG ProfileSourceDerivedEventMinimum;
  109. ULONGLONG ProfilePerfMonDataMaximumCount;
  110. ULONGLONG ProfilePerfMonCnfg0ClearStatusMask;
  111. ULONGLONG ProfilePerfMonCnfg1ClearStatusMask;
  112. ULONGLONG ProfilePerfMonCnfg2ClearStatusMask;
  113. ULONGLONG ProfilePerfMonCnfg3ClearStatusMask;
  114. } HalpProfileInfo = {
  115. //
  116. // Default IA64 Profiling to McKinley-core
  117. //
  118. // Note that different models in a family might have different PMU implementations.
  119. //
  120. HALP_PROFILE_IA64_MCKINLEY,
  121. TRUE,
  122. 0,
  123. NUMBER_OF_PERFMON_REGISTER_PAIRS,
  124. HalpMcKinleyProfileMapping,
  125. ProfileMcKinleyMaximum,
  126. ProfileMcKinleyDerivedEventMinimum,
  127. HalpMcKinleyPerfMonDataMaximumCount,
  128. HALP_PMC0_CLEAR_STATUS_MASK,
  129. HALP_PMC1_CLEAR_STATUS_MASK,
  130. HALP_PMC2_CLEAR_STATUS_MASK,
  131. HALP_PMC3_CLEAR_STATUS_MASK
  132. };
  133. #define HalpProfileIA64MicroArchitecture HalpProfileInfo.ProfileMicroArchitecture
  134. #define HalpProfileMapping HalpProfileInfo.ProfileMapping
  135. #define HalpProfileIA64Maximum HalpProfileInfo.ProfileSourceMaximum
  136. #define HalpProfileIA64DerivedEventMinimum HalpProfileInfo.ProfileSourceDerivedEventMinimum
  137. #define HalpPerfMonGenericPairs HalpProfileInfo.ProfilePerfMonGenericPairs
  138. #define HalpPerfMonDataMaximumCount HalpProfileInfo.ProfilePerfMonDataMaximumCount
  139. #define HalpPerfMonCnfg0FreezeBitInterrupt HalpProfileInfo.ProfilePerfMonCnfg0FreezeBitInterrupt
  140. #define HalpPerfMonCnfg0ClearStatusMask HalpProfileInfo.ProfilePerfMonCnfg0ClearStatusMask
  141. #define HalpPerfMonCnfg1ClearStatusMask HalpProfileInfo.ProfilePerfMonCnfg1ClearStatusMask
  142. #define HalpPerfMonCnfg2ClearStatusMask HalpProfileInfo.ProfilePerfMonCnfg2ClearStatusMask
  143. #define HalpPerfMonCnfg3ClearStatusMask HalpProfileInfo.ProfilePerfMonCnfg3ClearStatusMask
  144. //
  145. // End of HALIA64 Profile IA64 MicroArchitecture NameSpace
  146. //
  147. ////////////////
  148. //
  149. // HALIA64 Profile Source Mapping macros:
  150. //
  151. #define HalpDisactivateProfileSource( _ProfileSource ) ((_ProfileSource) = HalpProfileIA64Maximum)
  152. #define HalpIsProfileSourceActive( _ProfileSource ) ((_ProfileSource) != HalpProfileIA64Maximum)
  153. #define HalpIsProfileMappingInvalid( _ProfileMapping ) \
  154. (!(_ProfileMapping) || ((_ProfileMapping)->Supported == FALSE))
  155. // HalpIsProfileSourceDerivedEvent assumes ProfileMapping is valid and supported.
  156. #define HalpIsProfileSourceDerivedEvent( _ProfileSource, _ProfileMapping ) \
  157. (((_ProfileSource) >= (KPROFILE_SOURCE)HalpProfileIA64DerivedEventMinimum) || \
  158. ((_ProfileMapping)->Event >= 0x100))
  159. VOID
  160. HalpSetProfileMicroArchitecture(
  161. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  162. )
  163. /*++
  164. Routine Description:
  165. This function sets the HAL Profile MicroArchitecture namespace.
  166. Arguments:
  167. None.
  168. Return Value:
  169. None.
  170. --*/
  171. {
  172. ULONGLONG cpuFamily;
  173. PIA64_PERFMON_INFO perfMonInfo;
  174. USHORT genericPairs;
  175. cpuFamily = ((LoaderBlock->u.Ia64.ProcessorConfigInfo.CpuId3) >> 24) & 0xff;
  176. perfMonInfo = &LoaderBlock->u.Ia64.ProcessorConfigInfo.PerfMonInfo;
  177. HalpPerfMonDataMaximumCount =
  178. ((((ULONGLONG)1)<<(perfMonInfo->ImplementedCounterWidth))-1);
  179. genericPairs = HalpPerfMonGenericPairs = (USHORT) perfMonInfo->PerfMonGenericPairs;
  180. #if 0
  181. // 03/2002 FIXFIX ToBeTested.
  182. HalpPerfMonCnfg3ClearStatusMask = (genericPairs > 192) ? ((ULONGLONG)-1) << (genericPairs - 192)
  183. : HALP_PMC3_CLEAR_STATUS_MASK;
  184. HalpPerfMonCnfg2ClearStatusMask = (genericPairs > 128) ? ((ULONGLONG)-1) << (genericPairs - 128)
  185. : HALP_PMC2_CLEAR_STATUS_MASK;
  186. HalpPerfMonCnfg1ClearStatusMask = (genericPairs > 64) ? ((ULONGLONG)-1) << (genericPairs - 64)
  187. : HALP_PMC1_CLEAR_STATUS_MASK;
  188. HalpPerfMonCnfg0ClearStatusMask = (genericPairs > 4) ? ((((ULONGLONG)-1) << (genericPairs + 4)) | 0x0E)
  189. : HALP_PMC0_CLEAR_STATUS_MASK;
  190. #else
  191. HalpPerfMonCnfg3ClearStatusMask = HALP_PMC3_CLEAR_STATUS_MASK;
  192. HalpPerfMonCnfg2ClearStatusMask = HALP_PMC2_CLEAR_STATUS_MASK;
  193. HalpPerfMonCnfg1ClearStatusMask = HALP_PMC1_CLEAR_STATUS_MASK;
  194. HalpPerfMonCnfg0ClearStatusMask = HALP_PMC0_CLEAR_STATUS_MASK;
  195. if ( genericPairs > 192 ) {
  196. HalpPerfMonCnfg3ClearStatusMask = ((ULONGLONG)-1) << (genericPairs - 192);
  197. }
  198. else if ( genericPairs > 128 ) {
  199. HalpPerfMonCnfg2ClearStatusMask = ((ULONGLONG)-1) << (genericPairs - 128);
  200. }
  201. else if ( genericPairs > 64 ) {
  202. HalpPerfMonCnfg1ClearStatusMask = ((ULONGLONG)-1) << (genericPairs - 64);
  203. }
  204. else {
  205. HalpPerfMonCnfg0ClearStatusMask = ((((ULONGLONG)-1) << (genericPairs + 4)) | 0x0E);
  206. }
  207. #endif
  208. //
  209. // HALIA64 SW default profile microarchitecture is McKinley.
  210. //
  211. if (cpuFamily == 0x7) { // Merced
  212. HalpProfileIA64MicroArchitecture = HALP_PROFILE_IA64_MERCED;
  213. HalpProfileIA64Maximum = ProfileMercedMaximum;
  214. HalpProfileMapping = HalpMercedProfileMapping;
  215. HalpProfileIA64DerivedEventMinimum = ProfileMercedDerivedEventMinimum;
  216. HalpPerfMonCnfg0FreezeBitInterrupt = FALSE;
  217. }
  218. //
  219. // XXTF FIXFIX - 03/02
  220. // ASSERTMSG assertions are missing to correlate HALIA64 defaults and OSLOADER PERFMON_INFO data.
  221. //
  222. return;
  223. } // HalpSetProfileMicroArchitecture()
  224. VOID
  225. HalpEnableProfileCounting (
  226. VOID
  227. )
  228. /*++
  229. Routine Description:
  230. This function enables the profile counters to increment.
  231. This function is the counterpart of HalpDisableProfileCounting().
  232. Arguments:
  233. None.
  234. Return Value:
  235. None.
  236. --*/
  237. {
  238. ULONGLONG Data, ClearStatusMask;
  239. //
  240. // Clear PMC0.fr - bit 0.
  241. // Clear PMCO,1,2,3 OverFlow Bits.
  242. //
  243. HalpClearPerfMonCnfgOverflows( HalpPerfMonCnfg0ClearStatusMask,
  244. HalpPerfMonCnfg1ClearStatusMask,
  245. HalpPerfMonCnfg2ClearStatusMask,
  246. HalpPerfMonCnfg3ClearStatusMask );
  247. if ( HalpPerfMonCnfg0FreezeBitInterrupt ) {
  248. HalpUnFreezeProfileCounting();
  249. }
  250. return;
  251. } // HalpEnableProfileCounting()
  252. VOID
  253. HalpDisableProfileCounting (
  254. VOID
  255. )
  256. /*++
  257. Routine Description:
  258. This function disables the profile counters to increment.
  259. This function is the counterpart of HalpEnableProfileCounting().
  260. Arguments:
  261. None.
  262. Return Value:
  263. None.
  264. --*/
  265. {
  266. if ( HalpPerfMonCnfg0FreezeBitInterrupt ) {
  267. HalpFreezeProfileCounting();
  268. }
  269. else {
  270. HalpWritePerfMonCnfgReg0( HalpReadPerfMonCnfgReg0() | 0x1 );
  271. }
  272. return;
  273. } // HalpDisableProfileCounting()
  274. VOID
  275. HalpSetupProfilingPhase0(
  276. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  277. )
  278. /*++
  279. Routine Description:
  280. This function is called at HalInitSystem - phase 0 time to set
  281. the initial state of processor and profiling os subsystem with
  282. regards to the profiling functionality.
  283. Arguments:
  284. None.
  285. Return Value:
  286. None.
  287. Implementation Note:
  288. Executed at Phase 0 on Monarch processor.
  289. --*/
  290. {
  291. // Set the Profile MicroArchitecture namespace based on
  292. // the monarch processor.
  293. HalpSetProfileMicroArchitecture( LoaderBlock );
  294. return;
  295. } // HalpSetupProfilingPhase0()
  296. VOID
  297. HalpSetProfileCounterInterval (
  298. IN ULONG Counter,
  299. IN LONGLONG NextCount
  300. )
  301. /*++
  302. Routine Description:
  303. This function preloads the specified counter with a count value
  304. of 2^IMPL_BITS - NextCount.
  305. Arguments:
  306. Counter - Supplies the performance counter register number.
  307. NextCount - Supplies the value to preload in the monitor.
  308. An external interruption will be generated after NextCount.
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. LONGLONG Count;
  314. // if ( (Counter < 4) || (Counter > 7) ) return;
  315. Count = (HalpPerfMonDataMaximumCount + 1) - NextCount;
  316. if ( (ULONGLONG)Count >= HalpPerfMonDataMaximumCount ) {
  317. Count = 0;
  318. }
  319. HalpWritePerfMonDataReg( Counter, (ULONGLONG)Count );
  320. return;
  321. } // HalpSetProfileCounterInterval()
  322. VOID
  323. HalpSetProfileCounterPrivilegeLevelMask(
  324. IN ULONG Counter,
  325. IN ULONG Mask
  326. )
  327. /*++
  328. Routine Description:
  329. This function set the profile counter privilege level mask.
  330. Arguments:
  331. Counter - Supplies the performance counter register number.
  332. Mask - Supplies the privilege level mask to program the PMC with.
  333. Return Value:
  334. None.
  335. --*/
  336. {
  337. ULONGLONG data, plmMask;
  338. // if ( (Counter < 4) || (Counter > 7) ) return;
  339. plmMask = Mask & 0xF;
  340. data = HalpReadPerfMonCnfgReg( Counter );
  341. data &= ~0xF;
  342. data |= plmMask;
  343. HalpWritePerfMonCnfgReg( Counter, data );
  344. return;
  345. } // HalpSetProfileCounterPrivilegeLevelMask()
  346. VOID
  347. HalpEnableProfileCounterOverflowInterrupt (
  348. IN ULONG Counter
  349. )
  350. /*++
  351. Routine Description:
  352. This function enables the delivery of an overflow interrupt for
  353. the specified profile counter.
  354. Arguments:
  355. Counter - Supplies the performance counter register number.
  356. Return Value:
  357. None.
  358. --*/
  359. {
  360. ULONGLONG data, mask;
  361. // if ( (Counter < 4) || (Counter > 7) ) return;
  362. mask = 1<<5;
  363. data = HalpReadPerfMonCnfgReg( Counter );
  364. data |= mask;
  365. HalpWritePerfMonCnfgReg( Counter, data );
  366. return;
  367. } // HalpEnableProfileCounterOverflowInterrupt()
  368. VOID
  369. HalpDisableProfileCounterOverflowInterrupt (
  370. IN ULONG Counter
  371. )
  372. /*++
  373. Routine Description:
  374. This function disables the delivery of an overflow interrupt for
  375. the specified profile counter.
  376. Arguments:
  377. Counter - Supplies the performance counter register number.
  378. Return Value:
  379. None.
  380. --*/
  381. {
  382. ULONGLONG data, mask;
  383. // if ( (Counter < 4) || (Counter > 7) ) return;
  384. mask = 1<<5;
  385. data = HalpReadPerfMonCnfgReg( Counter );
  386. data &= ~mask;
  387. HalpWritePerfMonCnfgReg( Counter, data );
  388. return;
  389. } // HalpDisableProfileCounterOverflowInterrupt()
  390. VOID
  391. HalpEnableProfileCounterPrivilegeMonitor(
  392. IN ULONG Counter
  393. )
  394. /*++
  395. Routine Description:
  396. This function enables the profile counter as privileged monitor.
  397. Arguments:
  398. Counter - Supplies the performance counter register number.
  399. Return Value:
  400. None.
  401. --*/
  402. {
  403. ULONGLONG data, pm;
  404. // if ( (Counter < 4) || (Counter > 7) ) return;
  405. pm = 1<<6;
  406. data = HalpReadPerfMonCnfgReg( Counter );
  407. data |= pm;
  408. HalpWritePerfMonCnfgReg( Counter, data );
  409. return;
  410. } // HalpEnableProfileCounterPrivilegeMonitor()
  411. VOID
  412. HalpDisableProfileCounterPrivilegeMonitor(
  413. IN ULONG Counter
  414. )
  415. /*++
  416. Routine Description:
  417. This function disables the profile counter as privileged monitor.
  418. Arguments:
  419. Counter - Supplies the performance counter register number.
  420. Return Value:
  421. None.
  422. --*/
  423. {
  424. ULONGLONG data, pm;
  425. // if ( (Counter < 4) || (Counter > 7) ) return;
  426. pm = 1<<6;
  427. data = HalpReadPerfMonCnfgReg( Counter );
  428. data &= ~pm;
  429. HalpWritePerfMonCnfgReg( Counter, data );
  430. return;
  431. } // HalpDisableProfileCounterPrivilegeMonitor()
  432. VOID
  433. HalpSetProfileCounterEvent(
  434. IN ULONG Counter,
  435. IN ULONG Event
  436. )
  437. /*++
  438. Routine Description:
  439. The function specifies the monitor event for the profile counter.
  440. Arguments:
  441. Counter - Supplies the performance counter register number.
  442. Event - Supplies the monitor event code.
  443. Return Value:
  444. None.
  445. --*/
  446. {
  447. ULONGLONG data, es;
  448. // if ( (Counter < 4) || (Counter > 7) ) return;
  449. es = (Event & 0x7F) << 8;
  450. data = HalpReadPerfMonCnfgReg( Counter );
  451. data &= ~(0x7F << 8);
  452. data |= es;
  453. HalpWritePerfMonCnfgReg( Counter, data );
  454. return;
  455. } // HalpSetProfileCounterEvent()
  456. VOID
  457. HalpSetProfileCounterUmask(
  458. IN ULONG Counter,
  459. IN ULONG Umask
  460. )
  461. /*++
  462. Routine Description:
  463. This function sets the event specific umask value for the profile
  464. counter.
  465. Arguments:
  466. Counter - Supplies the performance counter register number.
  467. Umask - Supplies the event specific umask value.
  468. Return Value:
  469. None.
  470. --*/
  471. {
  472. ULONGLONG data, um;
  473. // if ( (Counter < 4) || (Counter > 7) ) return;
  474. um = (Umask & 0xF) << 16;
  475. data = HalpReadPerfMonCnfgReg( Counter );
  476. data &= ~(0xF << 16);
  477. data |= um;
  478. HalpWritePerfMonCnfgReg( Counter, data );
  479. return;
  480. } // HalpSetProfileCounterUmask()
  481. VOID
  482. HalpSetProfileCounterThreshold(
  483. IN ULONG Counter,
  484. IN ULONG Threshold
  485. )
  486. /*++
  487. Routine Description:
  488. This function sets the profile counter threshold.
  489. Arguments:
  490. Counter - Supplies the performance counter register number.
  491. Threshold - Supplies the desired threshold.
  492. This is related to multi-occurences events.
  493. Return Value:
  494. None.
  495. --*/
  496. {
  497. ULONGLONG data, reset, th;
  498. switch( Counter ) {
  499. case 4:
  500. case 5:
  501. Threshold &= 0x7;
  502. reset = ~(0x7 << 20);
  503. break;
  504. case 6:
  505. case 7:
  506. Threshold &= 0x3;
  507. reset = ~(0x3 << 20);
  508. break;
  509. default:
  510. return;
  511. }
  512. th = Threshold << 20;
  513. data = HalpReadPerfMonCnfgReg( Counter );
  514. data &= reset;
  515. data |= th;
  516. HalpWritePerfMonCnfgReg( Counter, data );
  517. return;
  518. } // HalpSetProfileCounterThreshold()
  519. VOID
  520. HalpSetProfileCounterInstructionSetMask(
  521. IN ULONG Counter,
  522. IN ULONG Mask
  523. )
  524. /*++
  525. Routine Description:
  526. This function sets the instruction set mask for the profile counter.
  527. Arguments:
  528. Counter - Supplies the performance counter register number.
  529. Mask - Supplies the instruction set mask.
  530. Return Value:
  531. None.
  532. --*/
  533. {
  534. ULONGLONG data, ismMask;
  535. // if ( (Counter < 4) || (Counter > 7) ) return;
  536. ismMask = (Mask & 0x3) << 24;
  537. data = HalpReadPerfMonCnfgReg( Counter );
  538. data &= ~(0x3 << 24);
  539. data |= ismMask;
  540. HalpWritePerfMonCnfgReg( Counter, data );
  541. return;
  542. } // HalpSetProfileCounterInstructionSetMask()
  543. ULONGLONG
  544. HalpSetProfileCounterConfiguration(
  545. IN ULONG Counter,
  546. IN ULONG PrivilegeMask,
  547. IN ULONG EnableOverflowInterrupt,
  548. IN ULONG EnablePrivilegeMonitor,
  549. IN ULONG Event,
  550. IN ULONG Umask,
  551. IN ULONG Threshold,
  552. IN ULONG InstructionSetMask
  553. )
  554. /*++
  555. Function Description:
  556. This function sets the profile counter with the specified parameters.
  557. Arguments:
  558. IN ULONG Counter -
  559. IN ULONG PrivilegeMask -
  560. IN ULONG EnableOverflowInterrupt -
  561. IN ULONG EnablePrivilegeMonitor -
  562. IN ULONG Event -
  563. IN ULONG Umask -
  564. IN ULONG Threshold -
  565. IN ULONG InstructionSetMask -
  566. Return Value:
  567. VOID
  568. Algorithm:
  569. ToBeSpecified
  570. In/Out Conditions:
  571. ToBeSpecified
  572. Globals Referenced:
  573. ToBeSpecified
  574. Exception Conditions:
  575. ToBeSpecified
  576. MP Conditions:
  577. ToBeSpecified
  578. Notes:
  579. This function is a kind of combo of the different profile counter APIs.
  580. It was created to provide speed.
  581. ToDo List:
  582. - Setting the threshold is not yet supported.
  583. Modification History:
  584. 3/16/2000 TF Initial version
  585. --*/
  586. {
  587. ULONGLONG data, plmMask, ismMask, es, um, th;
  588. // if ( (Counter < 4) || (Counter > 7) ) return;
  589. plmMask = (PrivilegeMask & 0xF);
  590. es = (Event & 0x7F) << 8;
  591. um = (Umask & 0xF) << 16;
  592. // XXTF - ToBeDone - Threshold not supported yet.
  593. ismMask = (InstructionSetMask & 0x3) << 24;
  594. data = HalpReadPerfMonCnfgReg( Counter );
  595. HalDebugPrint(( HAL_PROFILE, "HalpSetProfileCounterConfiguration: Counter = %ld Read = 0x%I64x\n", Counter, data ));
  596. data &= ~( (0x3 << 24) | (0xF << 16) | (0x7F << 8) | 0xF );
  597. data |= ( plmMask | es | um | ismMask );
  598. data = EnableOverflowInterrupt ? (data | (1<<5)) : (data & ~(1<<5));
  599. data = EnablePrivilegeMonitor ? (data | (1<<6)) : (data & ~(1<<6));
  600. HalpWritePerfMonCnfgReg( Counter, data );
  601. HalDebugPrint(( HAL_PROFILE, "HalpSetProfileCounterConfiguration: Counter = %ld Written = 0x%I64x\n", Counter, data ));
  602. return data;
  603. } // HalpSetProfileCounterConfiguration()
  604. BOOLEAN
  605. HalpIsProfileSourceEventEnabled(
  606. IN ULONG Event
  607. )
  608. {
  609. #define HalpProfileCnfgEvent( _Cnfg ) ((ULONG)((_Cnfg)>>8) & 0x7F)
  610. if ( HalpProfileCnfg4 && (HalpProfileCnfgEvent(HalpProfileCnfg4) == Event)) {
  611. return TRUE;
  612. }
  613. if ( HalpProfileCnfg5 && (HalpProfileCnfgEvent(HalpProfileCnfg5) == Event)) {
  614. return TRUE;
  615. }
  616. if ( HalpProfileCnfg6 && (HalpProfileCnfgEvent(HalpProfileCnfg6) == Event)) {
  617. return TRUE;
  618. }
  619. if ( HalpProfileCnfg7 && (HalpProfileCnfgEvent(HalpProfileCnfg7) == Event)) {
  620. return TRUE;
  621. }
  622. return FALSE;
  623. } // HalpIsProfileSourceEventEnabled()
  624. PHALP_PROFILE_MAPPING
  625. HalpGetProfileMapping(
  626. IN KPROFILE_SOURCE Source
  627. )
  628. /*++
  629. Routine Description:
  630. Given a profile source, returns whether or not that source is
  631. supported.
  632. Arguments:
  633. Source - Supplies the profile source
  634. Return Value:
  635. ProfileMapping entry - Profile source is supported
  636. NULL - Profile source is not supported
  637. --*/
  638. {
  639. if ( (ULONG) Source > HalpProfileIA64Maximum )
  640. {
  641. return NULL;
  642. }
  643. return(&HalpProfileMapping[Source]);
  644. } // HalpGetProfileMapping()
  645. ULONG // == ProfileCounter
  646. HalpApplyProfileSourceEventMaskPolicy(
  647. ULONG ProfileSourceEventMask
  648. )
  649. {
  650. ULONG pmcd, set;
  651. ULONG eventMask = ProfileSourceEventMask;
  652. set = eventMask >> PMCD_MASK_SET_PMCD_SHIFT;
  653. if ( set ) {
  654. KPROFILE_SOURCE profileSource;
  655. PHALP_PROFILE_MAPPING profileMapping;
  656. pmcd = (eventMask >> PMCD_MASK_SET_PMCD_SHIFT) & PMCD_MASK_SET_PMCD;
  657. profileSource = HalpGetProfileSource( pmcd );
  658. if ( !HalpIsProfileSourceActive( profileSource ) ) {
  659. return pmcd;
  660. }
  661. profileMapping = HalpGetProfileMapping( profileSource );
  662. if ( ! HalpIsProfileMappingInvalid( profileMapping ) ) {
  663. ULONG sameSet = profileMapping->EventMask >> PMCD_MASK_SET_SHIFT;
  664. ASSERTMSG( "HAL!HalpApplyProfileSourceEventMaskPolicy: non-derived events are supported!\n", !HalpIsProfileSourceDerivedEvent( profileSource, profileMapping ) );
  665. if ( sameSet == set ) {
  666. // We are doing one extra but considering the number of counter pairs, this is not a
  667. // great performance impact.
  668. if ( (eventMask & PMCD_MASK_4) && !HalpIsProfileSourceActive( HalpProfileSource4 ) ) {
  669. return 4;
  670. }
  671. if ( (eventMask & PMCD_MASK_6) && !HalpIsProfileSourceActive( HalpProfileSource6 ) ) {
  672. return 6;
  673. }
  674. if ( (eventMask & PMCD_MASK_7) && !HalpIsProfileSourceActive( HalpProfileSource7 ) ) {
  675. return 7;
  676. }
  677. if ( (eventMask & PMCD_MASK_5) && !HalpIsProfileSourceActive( HalpProfileSource5 ) ) {
  678. return 5;
  679. }
  680. }
  681. }
  682. }
  683. else {
  684. if ( (eventMask & PMCD_MASK_4) && !HalpIsProfileSourceActive( HalpProfileSource4 ) ) {
  685. return 4;
  686. }
  687. if ( (eventMask & PMCD_MASK_5) && !HalpIsProfileSourceActive( HalpProfileSource5 ) ) {
  688. return 5;
  689. }
  690. if ( (eventMask & PMCD_MASK_6) && !HalpIsProfileSourceActive( HalpProfileSource6 ) ) {
  691. return 6;
  692. }
  693. if ( (eventMask & PMCD_MASK_7) && !HalpIsProfileSourceActive( HalpProfileSource7 ) ) {
  694. return 7;
  695. }
  696. }
  697. return 0; // invalid PMC-PMD pair number.
  698. } // HalpApplyProfileSourceEventMaskPolicy()
  699. NTSTATUS
  700. HalpApplyProfileSourceEventPolicies(
  701. IN PHALP_PROFILE_MAPPING ProfileMapping,
  702. IN KPROFILE_SOURCE ProfileSource,
  703. OUT PULONG ProfileCounter,
  704. OUT HALP_PROFILE_MAPPING ProfileDerivedMapping[]
  705. )
  706. /*++
  707. Routine Description:
  708. This function executes the different policies defined for the Event of the specified
  709. Profile Source.
  710. Arguments:
  711. ProfileMapping - Supplies the Profile Mapping entry.
  712. ProfileSource - Supplies the Profile Source corresponding to the Profile Mapping entry.
  713. EventMask - Supplies a pointer to an Event Mask variable.
  714. ProfileDerivedMapping - Supplies a HALP_PROFILE_MAPPING array of derived counters for the
  715. passed event if it is derived.
  716. Return Value:
  717. STATUS_SUCCESS -
  718. STATUS_INVALID_PARAMETER -
  719. STATUS_UNSUCESSFUL -
  720. Implementation Note:
  721. The profile counting is disabled when this function is entered.
  722. --*/
  723. {
  724. ULONG pmcd;
  725. BOOLEAN eventDerived;
  726. if ( ! ProfileMapping ) {
  727. return STATUS_INVALID_PARAMETER;
  728. }
  729. ASSERTMSG( "HAL!HalpApplyProfileSourceEventPolicies: ProfileCounter is NULL!\n", ProfileCounter ) ;
  730. ASSERTMSG( "HAL!HalpApplyProfileSourceEventPolicies: ProfileDerivedMapping is NULL!\n", ProfileDerivedMapping ) ;
  731. *ProfileCounter = 0;
  732. ProfileDerivedMapping[0].Supported = FALSE;
  733. eventDerived = FALSE;
  734. //
  735. // Is this ProfileSource a derived event?
  736. //
  737. // If this is the case:
  738. // - We must get the policy applied to this source and apply it.
  739. // As an example, it could be coupled to the CPU_CYCLE event.
  740. // In that case, we would compute CPU_CYCLES interval for the
  741. // specified derived event interval, program the counter(s) and
  742. // the CPU_CYCLES event.
  743. //
  744. eventDerived = HalpIsProfileSourceDerivedEvent( ProfileSource, ProfileMapping );
  745. if ( eventDerived ) {
  746. NTSTATUS status;
  747. #if defined(HALP_PROFILE_DERIVED_EVENTS)
  748. // DerivedEvent not implemented yet - FIXFIX 04/2002
  749. status = ProfileMapping->DerivedEventInitialize( ProfileMapping,
  750. ProfileSource,
  751. &cpuCycles
  752. );
  753. #else
  754. status = STATUS_NOT_SUPPORTED;
  755. #endif
  756. if ( !NT_SUCCESS( status ) ) {
  757. return status;
  758. }
  759. }
  760. //
  761. // A specific event can be enabled only once at a time per PMU.
  762. // This also has to be imposed because of the ProfileSource aliases that
  763. // could use identical events.
  764. //
  765. if ( HalpIsProfileSourceEventEnabled( ProfileMapping->Event ) ) {
  766. return STATUS_ALREADY_COMMITTED;
  767. }
  768. //
  769. // Apply EventMask policy for the Source and return the considered counter.
  770. //
  771. pmcd = HalpApplyProfileSourceEventMaskPolicy( ProfileMapping->EventMask );
  772. if ( !pmcd ) {
  773. return STATUS_UNSUCCESSFUL;
  774. }
  775. *ProfileCounter = pmcd;
  776. return STATUS_SUCCESS;
  777. } // HalpApplyProfileSourceEventPolicies()
  778. NTSTATUS
  779. HalpProgramProfileMapping(
  780. PHALP_PROFILE_MAPPING ProfileMapping,
  781. KPROFILE_SOURCE ProfileSource
  782. )
  783. /*++
  784. Routine Description:
  785. This function enables the profiling configuration for the event defined by the
  786. specified Profile Mapping entry.
  787. This function is the counterpart of HalpDeProgramProfileMapping().
  788. Arguments:
  789. ProfileMapping - Supplies the Profile Mapping entry.
  790. ProfileSource - Supplies the Profile Source corresponding to the Profile Mapping entry.
  791. Return Value:
  792. STATUS_SUCCESS -
  793. STATUS_INVALID_PARAMETER -
  794. STATUS_UNSUCESSFUL -
  795. Implementation Note:
  796. The profile counting is disabled when this function is entered.
  797. --*/
  798. {
  799. HALP_PROFILE_MAPPING profileDerivedMapping[PROCESSOR_IA64_PERFCOUNTERS_PAIRS];
  800. ULONG profileCounter = 0;
  801. ULONGLONG profileCounterConfig = 0;
  802. NTSTATUS status;
  803. //
  804. // Apply the Profile Source policies defining the configuration of the
  805. // the corresponding Event and determine if this event is a Derived Event for this
  806. // micro-architecture.
  807. //
  808. status = HalpApplyProfileSourceEventPolicies( ProfileMapping, ProfileSource, &profileCounter, profileDerivedMapping );
  809. if ( !NT_SUCCESS( status ) ) {
  810. return status;
  811. }
  812. ASSERTMSG( "HAL!HalpProgramProfileMapping: profileCounter is 0!\n", profileCounter ) ;
  813. //
  814. // Follow ProfileMapping attributes to configure PMU counter.
  815. //
  816. HalpSetProfileCounterInterval( profileCounter, ProfileMapping->Interval );
  817. profileCounterConfig = HalpSetProfileCounterConfiguration( profileCounter,
  818. ProfileMapping->PrivilegeLevel,
  819. ProfileMapping->OverflowInterrupt,
  820. ProfileMapping->PrivilegeEnable,
  821. ProfileMapping->Event,
  822. ProfileMapping->UnitMask,
  823. ProfileMapping->Threshold,
  824. ProfileMapping->InstructionSetMask
  825. );
  826. HalpSetProfileSource( profileCounter, ProfileSource, profileCounterConfig );
  827. return STATUS_SUCCESS;
  828. } // HalpProgramProfileMapping()
  829. VOID
  830. HalpDeProgramProfileMapping(
  831. PHALP_PROFILE_MAPPING ProfileMapping,
  832. KPROFILE_SOURCE ProfileSource
  833. )
  834. /*++
  835. Routine Description:
  836. This function disables the profiling configuration for the event defined by the
  837. specified Profile Mapping entry.
  838. This function is the counterpart of HalpProgramProfileMapping().
  839. Arguments:
  840. ProfileMapping - Supplies the Profile Mapping entry.
  841. ProfileSource - Supplies the Profile Source corresponding to the Profile Mapping entry.
  842. Return Value:
  843. STATUS_SUCCESS -
  844. STATUS_INVALID_PARAMETER -
  845. STATUS_UNSUCESSFUL -
  846. --*/
  847. {
  848. NTSTATUS status;
  849. ULONG eventMask;
  850. ULONG eventFailedSpeculativeCheckLoads;
  851. ULONG eventALATOverflows;
  852. if ( ! ProfileMapping ) {
  853. return;
  854. }
  855. //
  856. // Is this ProfileSource a derived event?
  857. //
  858. // XXTF - ToBeDone - Derived Event
  859. //
  860. // Validate the Profile Source as active.
  861. //
  862. if ( HalpProfileSource4 == ProfileSource ) {
  863. HalpProfileCnfg4 = HalpSetProfileCounterConfiguration( 4,
  864. PMC_PLM_NONE,
  865. PMC_DISABLE_OVERFLOW_INTERRUPT,
  866. PMC_DISABLE_PRIVILEGE_MONITOR,
  867. 0, // Event
  868. 0, // Umask
  869. 0, // Threshold
  870. PMC_ISM_NONE
  871. );
  872. HalpSetProfileCounterInterval( 4, 0 );
  873. HalpDisactivateProfileSource( HalpProfileSource4 );
  874. HalpProfilingRunning--;
  875. }
  876. else if ( HalpProfileSource5 == ProfileSource ) {
  877. HalpProfileCnfg5 = HalpSetProfileCounterConfiguration( 5,
  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( 5, 0 );
  887. HalpDisactivateProfileSource( HalpProfileSource5 );
  888. HalpProfilingRunning--;
  889. }
  890. else if ( HalpProfileSource6 == ProfileSource ) {
  891. HalpProfileCnfg6 = HalpSetProfileCounterConfiguration( 6,
  892. PMC_PLM_NONE,
  893. PMC_DISABLE_OVERFLOW_INTERRUPT,
  894. PMC_DISABLE_PRIVILEGE_MONITOR,
  895. 0, // Event
  896. 0, // Umask
  897. 0, // Threshold
  898. PMC_ISM_NONE
  899. );
  900. HalpSetProfileCounterInterval( 6, 0 );
  901. HalpDisactivateProfileSource( HalpProfileSource6);
  902. HalpProfilingRunning--;
  903. }
  904. else if ( HalpProfileSource7 == ProfileSource ) {
  905. HalpProfileCnfg7 = HalpSetProfileCounterConfiguration( 7,
  906. PMC_PLM_NONE,
  907. PMC_DISABLE_OVERFLOW_INTERRUPT,
  908. PMC_DISABLE_PRIVILEGE_MONITOR,
  909. 0, // Event
  910. 0, // Umask
  911. 0, // Threshold
  912. PMC_ISM_NONE
  913. );
  914. HalpSetProfileCounterInterval( 7, 0 );
  915. HalpDisactivateProfileSource( HalpProfileSource7 );
  916. HalpProfilingRunning--;
  917. }
  918. return;
  919. } // HalpDeProgramProfileMapping()
  920. ULONG_PTR
  921. HalpSetProfileInterruptHandler(
  922. IN ULONG_PTR ProfileInterruptHandler
  923. )
  924. /*++
  925. Routine Description:
  926. This function registers a per-processor Profiling Interrupt Handler.
  927. Arguments:
  928. ProfileInterruptHandler - Interrupt Handler.
  929. Return Value:
  930. (ULONG_PTR)STATUS_SUCCESS - Successful registration.
  931. (ULONG_PTR)STATUS_ALREADY_COMMITTED - Cannot register an handler if profiling events are running.
  932. (ULONG_PTR)STATUS_PORT_ALREADY_SET - An Profiling Interrupt Handler was already registred - not imposed currently.
  933. Note:
  934. IT IS THE RESPONSIBILITY OF THE CALLER OF THIS ROUTINE TO ENSURE
  935. THAT NO PAGE FAULTS WILL OCCUR DURING EXECUTION OF THE PROVIDED
  936. FUNCTION OR ACCESS TO THE PROVIDED CONTEXT.
  937. A MINIMUM OF FUNCTION POINTER CHECKING WAS DONE IN HalSetSystemInformation PROCESSING.
  938. --*/
  939. {
  940. //
  941. // If profiling is already running, we do not allow the handler registration.
  942. //
  943. // This imposes that:
  944. //
  945. // - if the default HAL profiling is running or a profiling with a registered interrupt
  946. // handler is running, we cannot register an interrupt handler.
  947. // In the last case, all the profiling events have to be stopped before a possible
  948. // registration.
  949. //
  950. // It should be also noticed that there is no ownership of profiling monitors implemented.
  951. // Meaning that if profiling is started, the registred handler will get the interrupts
  952. // generated by ALL the running monitor events if they are programmed to generate interrupts.
  953. //
  954. if ( HalpProfilingRunning ) {
  955. HalDebugPrint(( HAL_PROFILE, "HalpSetProfileInterruptHandler: Profiling already running\n" ));
  956. return((ULONG_PTR)(ULONG)(STATUS_ALREADY_COMMITTED));
  957. }
  958. #if 0
  959. //
  960. // Thierry - 03/2000. ToBeVerified.
  961. //
  962. // In case, no profiling was started, there is currently no restriction in registering
  963. // another handler if one was already registered.
  964. //
  965. if ( HalpProfillingInterruptHandler ) {
  966. return((ULONG_PTR)(ULONG)(STATUS_PORT_ALREADY_SET));
  967. }
  968. #endif // 0
  969. HalpProfilingInterruptHandler = (ULONGLONG)ProfileInterruptHandler;
  970. return((ULONG_PTR)(ULONG)(STATUS_SUCCESS));
  971. } // HalpSetProfileInterruptHandler()
  972. VOID
  973. HalpProfileInterrupt(
  974. IN PKINTERRUPT_ROUTINE Interrupt,
  975. IN PKTRAP_FRAME TrapFrame
  976. )
  977. /*++
  978. Routine Description:
  979. Default PROFILE_VECTOR Interrupt Handler.
  980. This function is executed as the result of an interrupt from the
  981. internal microprocessor performance counters. The interrupt
  982. may be used to signal the completion of a profile event.
  983. If profiling is current active, the function determines if the
  984. profile interval has expired and if so dispatches to the standard
  985. system routine to update the system profile time. If profiling
  986. is not active then returns.
  987. Arguments:
  988. TrapFrame - Trap frame address.
  989. Return Value:
  990. None.
  991. --*/
  992. {
  993. //
  994. // Call registered per-processor Profiling Interrupt handler if it exists.
  995. // We will return immediately before doing any default profiling interrupt handling.
  996. //
  997. if ( HalpProfilingInterruptHandler &&
  998. (*((PHAL_PROFILE_INTERRUPT_HANDLER)HalpProfilingInterruptHandler) != NULL) ) {
  999. (*((PHAL_PROFILE_INTERRUPT_HANDLER)HalpProfilingInterruptHandler))( TrapFrame );
  1000. return;
  1001. }
  1002. //
  1003. // Handle interrupt if profiling is enabled.
  1004. //
  1005. if ( HalpProfilingRunning ) {
  1006. //
  1007. // Process every PMC/PMD pair overflow.
  1008. //
  1009. // XXTF - FIXFIX - Merced specific.
  1010. UCHAR pmc0, overflow;
  1011. ULONG source;
  1012. HalpProfilingInterrupts++;
  1013. pmc0 = (UCHAR)HalpReadPerfMonCnfgReg0();
  1014. ASSERTMSG( "HAL!HalpProfileInterrupt PMC0 freeze bit is not set!\n", pmc0 & 0x1 );
  1015. overflow = pmc0 & 0xF0;
  1016. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", overflow );
  1017. if ( overflow & (1<<4) ) {
  1018. source = HalpProfileSource4; // XXTF - IfFaster - Coud used pmc.es
  1019. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < HalpProfileIA64Maximum );
  1020. KeProfileInterruptWithSource( TrapFrame, source );
  1021. HalpSetProfileCounterInterval( 4, HalpProfileMapping[source].Interval );
  1022. // XXTF - IfFaster - HalpWritePerfMonDataReg( 4, HalpProfileMapping[source].Interval );
  1023. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 4, *PCRProfileCnfg4Reload );
  1024. }
  1025. if ( overflow & (1<<5) ) {
  1026. source = HalpProfileSource5; // XXTF - IfFaster - Coud used pmc.es
  1027. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < HalpProfileIA64Maximum );
  1028. KeProfileInterruptWithSource( TrapFrame, source );
  1029. HalpSetProfileCounterInterval( 5, HalpProfileMapping[source].Interval );
  1030. // XXTF - IfFaster - HalpWritePerfMonDataReg( 5, HalpProfileMapping[source].Interval );
  1031. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 5, *PCRProfileCnfg5Reload );
  1032. }
  1033. if ( overflow & (1<<6) ) {
  1034. source = HalpProfileSource6; // XXTF - IfFaster - Coud used pmc.es
  1035. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < HalpProfileIA64Maximum );
  1036. KeProfileInterruptWithSource( TrapFrame, source );
  1037. HalpSetProfileCounterInterval( 6, HalpProfileMapping[source].Interval );
  1038. // XXTF - IfFaster - HalpWritePerfMonDataReg( 6, HalpProfileMapping[source].Interval );
  1039. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 6, *PCRProfileCnfg6Reload );
  1040. }
  1041. if ( overflow & (1<<7) ) {
  1042. source = HalpProfileSource7; // XXTF - IfFaster - Coud used pmc.es
  1043. ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < HalpProfileIA64Maximum );
  1044. KeProfileInterruptWithSource( TrapFrame, source );
  1045. HalpSetProfileCounterInterval( 7, HalpProfileMapping[source].Interval );
  1046. // XXTF - IfFaster - HalpWritePerfMonDataReg( 6, HalpProfileMapping[source].Interval );
  1047. // XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 7, *PCRProfileCnfg7Reload );
  1048. }
  1049. //
  1050. // Clear pmc0.fr and overflow bits.
  1051. //
  1052. HalpEnableProfileCounting();
  1053. }
  1054. else {
  1055. HalpProfilingInterruptsWithoutProfiling++;
  1056. }
  1057. return;
  1058. } // HalpProfileInterrupt()
  1059. NTSTATUS
  1060. HalSetProfileSourceInterval(
  1061. IN KPROFILE_SOURCE ProfileSource,
  1062. IN OUT ULONG_PTR *Interval
  1063. )
  1064. /*++
  1065. Routine Description:
  1066. Sets the profile interval for a specified profile source
  1067. Arguments:
  1068. ProfileSource - Supplies the profile source
  1069. Interval - Supplies the specified profile interval
  1070. Returns the actual profile interval
  1071. - if ProfileSource is ProfileTime, Interval is in 100ns units.
  1072. Return Value:
  1073. NTSTATUS
  1074. --*/
  1075. {
  1076. ULONGLONG countEvents;
  1077. PHALP_PROFILE_MAPPING profileMapping;
  1078. profileMapping = HalpGetProfileMapping(ProfileSource);
  1079. if ( profileMapping == NULL ) {
  1080. return( STATUS_NOT_IMPLEMENTED );
  1081. }
  1082. if ( profileMapping->Supported == FALSE ) {
  1083. return( STATUS_NOT_SUPPORTED );
  1084. }
  1085. //
  1086. // Fill in the profile source value.
  1087. //
  1088. profileMapping->ProfileSource = ProfileSource;
  1089. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: ProfileSource = %ld IN Desired Interval = 0x%Ix\n", ProfileSource, *Interval ));
  1090. countEvents = (ULONGLONG)*Interval;
  1091. if ( (ProfileSource == ProfileTime) && countEvents ) {
  1092. //
  1093. // Convert the clock tick period (in 100ns units) into a cycle count period
  1094. //
  1095. countEvents = (ULONGLONG)(countEvents * HalpITCTicksPer100ns);
  1096. }
  1097. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: countEvent = 0x%I64x\n", countEvents ));
  1098. //
  1099. // Check to see if the desired Interval is reasonable, if not adjust it.
  1100. //
  1101. // A specific case for desired Interval == 0, this resets the ProfileMapping entry Interval
  1102. // field and will make the event increment the PMD up to overflow bit if the Events generating
  1103. // caller is killed or does not stop the interrupts for any reason.
  1104. // Again, this is to avoid hanging the system with PMU interrupts.
  1105. //
  1106. if ( countEvents ) {
  1107. if ( countEvents > profileMapping->IntervalMax ) {
  1108. countEvents = profileMapping->IntervalMax;
  1109. }
  1110. else if ( countEvents < profileMapping->IntervalMin ) {
  1111. countEvents = profileMapping->IntervalMin;
  1112. }
  1113. }
  1114. profileMapping->Interval = countEvents;
  1115. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: CurrentInterval = 0x%I64x\n", profileMapping->Interval ));
  1116. if ( (ProfileSource == ProfileTime) && countEvents ) {
  1117. //
  1118. // Convert cycle count back into 100ns clock ticks
  1119. //
  1120. countEvents = (ULONGLONG)(countEvents / HalpITCTicksPer100ns);
  1121. }
  1122. *Interval = (ULONG_PTR)countEvents;
  1123. HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: ProfileSource = %ld OUT *Interval = 0x%Ix\n", ProfileSource, *Interval ));
  1124. return STATUS_SUCCESS;
  1125. } // HalSetProfileSourceInterval()
  1126. ULONG_PTR
  1127. HalSetProfileInterval (
  1128. IN ULONG_PTR Interval
  1129. )
  1130. /*++
  1131. Routine Description:
  1132. This routine sets the ProfileTime source interrupt interval.
  1133. Arguments:
  1134. Interval - Supplies the desired profile interval in 100ns units.
  1135. Return Value:
  1136. The actual profile interval.
  1137. --*/
  1138. {
  1139. ULONG_PTR NewInterval;
  1140. NewInterval = Interval;
  1141. HalSetProfileSourceInterval(ProfileTime, &NewInterval);
  1142. return(NewInterval);
  1143. } // HalSetProfileInterval()
  1144. VOID
  1145. HalStartProfileInterrupt (
  1146. KPROFILE_SOURCE ProfileSource
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. This routine turns on the profile interrupt.
  1151. N.B. This routine must be called at PROFILE_LEVEL on each processor.
  1152. Arguments:
  1153. None.
  1154. Return Value:
  1155. None.
  1156. --*/
  1157. {
  1158. BOOLEAN disabledProfileCounting;
  1159. NTSTATUS status;
  1160. PHALP_PROFILE_MAPPING profileMapping;
  1161. //
  1162. // Get the Hal profile mapping entry associated with the specified source.
  1163. //
  1164. profileMapping = HalpGetProfileMapping( ProfileSource );
  1165. if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
  1166. HalDebugPrint(( HAL_PROFILE, "HalStartProfileInterrupt: invalid source = %ld\n", ProfileSource ));
  1167. return;
  1168. }
  1169. //
  1170. // Disable the profile counting if enabled.
  1171. //
  1172. disabledProfileCounting = FALSE;
  1173. if ( HalpProfilingRunning && !(HalpReadPerfMonCnfgReg0() & 0x1) ) {
  1174. HalpDisableProfileCounting();
  1175. disabledProfileCounting = TRUE;
  1176. }
  1177. //
  1178. // Obtain and initialize an available PMC register that supports this event.
  1179. // We may enable more than one event.
  1180. // If the initialization failed, we return immediately.
  1181. //
  1182. // XXTF - FIXFIX - is there a way to
  1183. // * notify the caller for the failure and the reason of the failure. or
  1184. // * modify the API. or
  1185. // * define a new API.
  1186. //
  1187. status = HalpProgramProfileMapping( profileMapping, ProfileSource );
  1188. if ( !NT_SUCCESS(status) ) {
  1189. HalDebugPrint(( HAL_PROFILE, "HalStartProfileInterrupt: HalpProgramProfileMapping failed.\n" ));
  1190. if ( disabledProfileCounting ) {
  1191. HalpEnableProfileCounting();
  1192. }
  1193. return;
  1194. }
  1195. //
  1196. // Notify the profiling as active.
  1197. // before enabling the selected pmc overflow interrupt and unfreezing the counters.
  1198. //
  1199. HalpProfilingRunning++;
  1200. HalpEnableProfileCounting();
  1201. return;
  1202. } // HalStartProfileInterrupt()
  1203. VOID
  1204. HalStopProfileInterrupt (
  1205. KPROFILE_SOURCE ProfileSource
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. This routine turns off the profile interrupt.
  1210. N.B. This routine must be called at PROFILE_LEVEL on each processor.
  1211. Arguments:
  1212. ProfileSource - Supplies the Profile Source to stop.
  1213. Return Value:
  1214. None.
  1215. --*/
  1216. {
  1217. PHALP_PROFILE_MAPPING profileMapping;
  1218. //
  1219. // Get the Hal profile mapping entry associated with the specified profile source.
  1220. //
  1221. profileMapping = HalpGetProfileMapping( ProfileSource );
  1222. if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
  1223. HalDebugPrint(( HAL_PROFILE, "HalStopProfileInterrupt: invalid source = %ld\n", ProfileSource ));
  1224. return;
  1225. }
  1226. //
  1227. // Get and disable an available PMC register that supports this event.
  1228. // We might disable more than one event.
  1229. // If the initialization failed, we return immediately.
  1230. //
  1231. // XXTF - FIXFIX - is there a way to
  1232. // * notify the caller for the failure and the reason of the failure. or
  1233. // * modify the API. or
  1234. // * define a new API.
  1235. //
  1236. HalpDeProgramProfileMapping( profileMapping, ProfileSource );
  1237. return;
  1238. } // HalStopProfileInterrupt()
  1239. VOID
  1240. HalpResetProcessorDependentPerfMonCnfgRegs(
  1241. ULONGLONG DefaultValue
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. This routine initializes the processor dependent performance configuration
  1246. registers.
  1247. Arguments:
  1248. DefaultValue - default value used to initialize IA64 generic PMCs.
  1249. Return Value:
  1250. None.
  1251. --*/
  1252. {
  1253. // XXTF - 02/08/2000
  1254. // For now, there is no initialization for processor dependent performance
  1255. // configuration registers.
  1256. return;
  1257. } // HalpResetProcessorDependentPerfMonCnfgRegs()
  1258. VOID
  1259. HalpResetPerfMonCnfgRegs(
  1260. VOID
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. This routine initializes the IA64 architected performance configuration
  1265. registers and calls the micro-architecture specific initialization.
  1266. Arguments:
  1267. None.
  1268. Return Value:
  1269. None.
  1270. --*/
  1271. {
  1272. ULONG pmc;
  1273. ULONGLONG value;
  1274. value = HALP_PMC4_RESET;
  1275. pmc = 4;
  1276. HalpWritePerfMonCnfgReg( pmc, value );
  1277. value = HALP_PMC_RESET;
  1278. for ( pmc = 5; pmc < 8; pmc++ ) {
  1279. HalpWritePerfMonCnfgReg( pmc, value );
  1280. }
  1281. HalpResetProcessorDependentPerfMonCnfgRegs( value );
  1282. return;
  1283. } // HalpResetPerfMonCnfgRegs()
  1284. VOID
  1285. HalpEnablePMU(
  1286. VOID
  1287. )
  1288. /*++
  1289. Routine Description:
  1290. This routine enables the processor Performance Monitoring Unit.
  1291. Called from HalInitializeProfiling at phase 1 on every processor.
  1292. Arguments:
  1293. Number - Supplies the processor number.
  1294. Return Value:
  1295. None.
  1296. Implementation Notes:
  1297. Starting with McKinley, in order to use any of the PMU features,
  1298. a 1 should be written to the PMC4.23 bit. This controls the clocks
  1299. to all PMDs and all PMCs (with the exception of PMC4) and other
  1300. non-critical circuitry. This bit powers up as 1 and must be written
  1301. as 1, otherwise the PMU will not function correctly.
  1302. --*/
  1303. {
  1304. HalpWritePerfMonCnfgReg( 4, HALP_PMC4_RESET );
  1305. } // HalpEnablePMU()
  1306. VOID
  1307. HalpInitializeProfiling (
  1308. ULONG Number
  1309. )
  1310. /*++
  1311. Routine Description:
  1312. This routine is called during initialization to initialize profiling
  1313. for each processor in the system.
  1314. Called from HalInitSystem at phase 1 on every processor.
  1315. Arguments:
  1316. Number - Supplies the processor number.
  1317. Return Value:
  1318. None.
  1319. --*/
  1320. {
  1321. //
  1322. // Enable IA64 Processor PMU
  1323. //
  1324. HalpEnablePMU();
  1325. //
  1326. // Disable processor profile counting.
  1327. //
  1328. HalpDisableProfileCounting();
  1329. //
  1330. // If BSP processor, initialize the ProfileTime Interval entries.
  1331. //
  1332. // Assumes HalpITCTicksPer100ns has been initialized.
  1333. if ( Number == 0 ) {
  1334. ULONGLONG interval;
  1335. ULONGLONG count;
  1336. PHALP_PROFILE_MAPPING profile;
  1337. profile = &HalpProfileMapping[ProfileTime];
  1338. interval = DEFAULT_PROFILE_INTERVAL;
  1339. count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
  1340. profile->IntervalDef = count;
  1341. interval = MAXIMUM_PROFILE_INTERVAL;
  1342. count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
  1343. profile->IntervalMax = count;
  1344. interval = MINIMUM_PROFILE_INTERVAL;
  1345. count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
  1346. profile->IntervalMin = count;
  1347. }
  1348. //
  1349. // ToBeDone - checkpoint for default processor.PSR fields for
  1350. // performance monitoring.
  1351. //
  1352. //
  1353. // Resets the processor performance configuration registers.
  1354. //
  1355. HalpResetPerfMonCnfgRegs();
  1356. //
  1357. // Initialization of the Per processor profiling data.
  1358. //
  1359. HalpProfilingRunning = 0;
  1360. HalpDisactivateProfileSource( HalpProfileSource4 );
  1361. HalpDisactivateProfileSource( HalpProfileSource5 );
  1362. HalpDisactivateProfileSource( HalpProfileSource6 );
  1363. HalpDisactivateProfileSource( HalpProfileSource7 );
  1364. //
  1365. // XXTF 02/08/2000:
  1366. // Different performance vectors are considered:
  1367. // - Profiling (default) -> PROFILE_VECTOR
  1368. // - Tracing -> PERF_VECTOR [PMUTRACE_VECTOR]
  1369. //
  1370. // Set default Performance vector to Profiling.
  1371. //
  1372. ASSERTMSG( "HAL!HalpInitializeProfiler PROFILE_VECTOR handler != HalpProfileInterrupt\n",
  1373. PCR->InterruptRoutine[PROFILE_VECTOR] == (PKINTERRUPT_ROUTINE)HalpProfileInterrupt );
  1374. HalpWritePerfMonVectorReg( PROFILE_VECTOR );
  1375. return;
  1376. } // HalpInitializeProfiling()
  1377. NTSTATUS
  1378. HalpProfileSourceInformation (
  1379. OUT PVOID Buffer,
  1380. IN ULONG BufferLength,
  1381. OUT PULONG ReturnedLength
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. Returns the HAL_PROFILE_SOURCE_INFORMATION or
  1386. HAL_PROFILE_SOURCE_INFORMATION_EX for this processor.
  1387. Arguments:
  1388. Buffer - output buffer
  1389. BufferLength - length of buffer on input
  1390. ReturnedLength - The length of data returned
  1391. Return Value:
  1392. STATUS_SUCCESS - successful return.
  1393. STATUS_BUFFER_TOO_SMALL - passed buffer size is invalid
  1394. The ReturnedLength contains the buffersize mininum
  1395. STATUS_NOT_IMPLEMENTED - specified source is not implemented
  1396. STATUS_NOT_SUPPORTED - specified source is not supported
  1397. --*/
  1398. {
  1399. PHALP_PROFILE_MAPPING profileMapping;
  1400. NTSTATUS status = STATUS_SUCCESS;
  1401. KPROFILE_SOURCE source;
  1402. if ( (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) &&
  1403. (BufferLength < sizeof(HAL_PROFILE_SOURCE_INFORMATION_EX)) )
  1404. {
  1405. status = STATUS_INFO_LENGTH_MISMATCH;
  1406. return status;
  1407. }
  1408. source = ((PHAL_PROFILE_SOURCE_INFORMATION)Buffer)->Source;
  1409. profileMapping = HalpGetProfileMapping( source );
  1410. //
  1411. // return a different status error if the source is not supported or invalid.
  1412. //
  1413. if ( profileMapping == NULL ) {
  1414. status = STATUS_NOT_IMPLEMENTED;
  1415. return status;
  1416. }
  1417. if ( profileMapping->Supported == FALSE ) {
  1418. status = STATUS_NOT_SUPPORTED;
  1419. }
  1420. //
  1421. // Fill in the profile source value.
  1422. //
  1423. profileMapping->ProfileSource = source;
  1424. //
  1425. // and Fill in the information.
  1426. //
  1427. if ( BufferLength == sizeof(HAL_PROFILE_SOURCE_INFORMATION) ) {
  1428. PHAL_PROFILE_SOURCE_INFORMATION sourceInfo;
  1429. //
  1430. // HAL_PROFILE_SOURCE_INFORMATION buffer.
  1431. //
  1432. sourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
  1433. sourceInfo->Supported = profileMapping->Supported;
  1434. if ( sourceInfo->Supported ) {
  1435. //
  1436. // For ProfileTime, we convert cycle count back into 100ns clock ticks.
  1437. //
  1438. if ( profileMapping->ProfileSource == ProfileTime ) {
  1439. sourceInfo->Interval = (ULONG) (profileMapping->Interval / HalpITCTicksPer100ns);
  1440. }
  1441. else {
  1442. sourceInfo->Interval = (ULONG) profileMapping->Interval;
  1443. }
  1444. }
  1445. if ( ReturnedLength ) {
  1446. *ReturnedLength = sizeof(HAL_PROFILE_SOURCE_INFORMATION);
  1447. }
  1448. }
  1449. else {
  1450. PHAL_PROFILE_SOURCE_INFORMATION_EX sourceInfoEx;
  1451. //
  1452. // HAL_PROFILE_SOURCE_INFORMATION_EX buffer.
  1453. //
  1454. sourceInfoEx = (PHAL_PROFILE_SOURCE_INFORMATION_EX)Buffer;
  1455. sourceInfoEx->Supported = profileMapping->Supported;
  1456. if ( sourceInfoEx->Supported ) {
  1457. //
  1458. // For ProfileTime, we convert cycle count back into 100ns clock ticks.
  1459. //
  1460. if ( profileMapping->ProfileSource == ProfileTime ) {
  1461. sourceInfoEx->Interval =
  1462. (ULONG_PTR) (profileMapping->Interval / HalpITCTicksPer100ns);
  1463. }
  1464. else {
  1465. sourceInfoEx->Interval = (ULONG_PTR) profileMapping->Interval;
  1466. }
  1467. sourceInfoEx->DefInterval = (ULONG_PTR) profileMapping->IntervalDef;
  1468. sourceInfoEx->MaxInterval = (ULONG_PTR) profileMapping->IntervalMax;
  1469. sourceInfoEx->MinInterval = (ULONG_PTR) profileMapping->IntervalMin;
  1470. }
  1471. if ( ReturnedLength ) {
  1472. *ReturnedLength = sizeof(HAL_PROFILE_SOURCE_INFORMATION_EX);
  1473. }
  1474. }
  1475. return status;
  1476. } // HalpProfileSourceInformation()