pentiumALib.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:31k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pentiumALib.s - Pentium and PentiumPro specific routines */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01e,21aug01,hdn  added P5/P6 PMC routines
  7. 01d,24mar99,jdi  doc: added basic formatting commands, absent despite
  8.  thorough and long-standing coverage in WRS Coding Conventions.
  9. 01b,17apr98,hdn  fixed typo.
  10. 01b,17apr98,hdn  added documentation.
  11. 01a,09jul97,hdn  written.
  12. */
  13. /*
  14. DESCRIPTION
  15. This module contains Pentium and PentiumPro specific routines written in 
  16. assembly language.
  17. .SS "MCA (Machine Check Architecture)"
  18. The Pentium processor introduced a new exception called the machine-check 
  19. exception (interrupt-18).  This exception is used to signal hardware-related
  20. errors, such as a parity error on a read cycle.  The PentiumPro processor
  21. extends the types of errors that can be detected and that generate a machine-
  22. check exception.  It also provides a new machine-check architecture that
  23. records information about a machine-check error and provides the basis for an
  24. extended error logging capability.
  25. MCA is enabled and its status registers are cleared zero in sysHwInit().
  26. Its registers are accessed by pentiumMsrSet() and pentiumMsrGet().
  27. .SS "PMC (Performance Monitoring Counters)"
  28. The P5 and P6 family of processor has two performance-monitoring counters for
  29. use in monitoring internal hardware operations.  These counters are duration
  30. or event counters that can be programmed to count any of approximately 100
  31. different types of events, such as the number of instructions decoded, number
  32. of interrupts received, or number of cache loads. However, the set of events
  33. can be counted with PMC is different in the P5 and P6 family of processors;
  34. and the locations and bit difinitions of the related counter and control
  35. registers are also different. So there are two set of PMC routines, one for
  36. P6 family and one for p5 family respectively.
  37. There are nine routines to interface the PMC of P6 family processors.  These
  38. nine routines are:
  39. .CS
  40.   STATUS pentiumP6PmcStart
  41.          (
  42.  int pmcEvtSel0; /@ performance event select register 0 @/
  43.  int pmcEvtSel1; /@ performance event select register 1 @/
  44.          )
  45.   void   pentiumP6PmcStop (void)
  46.   void   pentiumP6PmcStop1 (void)
  47.   void   pentiumP6PmcGet
  48.  (
  49.  long long int * pPmc0; /@ performance monitoring counter 0 @/
  50.  long long int * pPmc1; /@ performance monitoring counter 1 @/
  51.  )
  52.   void   pentiumP6PmcGet0
  53.  (
  54.  long long int * pPmc0; /@ performance monitoring counter 0 @/
  55.  )
  56.   void   pentiumP6PmcGet1
  57.  (
  58.  long long int * pPmc1; /@ performance monitoring counter 1 @/
  59.  )
  60.   void   pentiumP6PmcReset (void)
  61.   void   pentiumP6PmcReset0 (void)
  62.   void   pentiumP6PmcReset1 (void)
  63. .CE
  64. pentiumP6PmcStart() starts both PMC0 and PMC1. 
  65. pentiumP6PmcStop() stops them, and pentiumP6PmcStop1() stops only PMC1.  
  66. pentiumP6PmcGet() gets contents of PMC0 and PMC1.  pentiumP6PmcGet0() gets
  67. contents of PMC0, and pentiumP6PmcGet1() gets contents of PMC1.
  68. pentiumP6PmcReset() resets both PMC0 and PMC1.  pentiumP6PmcReset0() resets
  69. PMC0, and pentiumP6PmcReset1() resets PMC1.
  70. PMC is enabled in sysHwInit().  Selected events in the default configuration
  71. are PMC0 = number of hardware interrupts received and PMC1 = number of 
  72. misaligned data memory references.
  73. There are ten routines to interface the PMC of P5 family processors.  These
  74. ten routines are:
  75. .CS
  76.   STATUS pentiumP5PmcStart0
  77.          (
  78.  int pmc0Cesr; /@ PMC0 control and event select @/
  79.          )
  80.   STATUS pentiumP5PmcStart1
  81.          (
  82.  int pmc1Cesr; /@ PMC1 control and event select @/
  83.          )
  84.   void   pentiumP5PmcStop0 (void)
  85.   void   pentiumP5PmcStop1 (void)
  86.   void   pentiumP5PmcGet
  87.  (
  88.  long long int * pPmc0; /@ performance monitoring counter 0 @/
  89.  long long int * pPmc1; /@ performance monitoring counter 1 @/
  90.  )
  91.   void   pentiumP5PmcGet0
  92.  (
  93.  long long int * pPmc0; /@ performance monitoring counter 0 @/
  94.  )
  95.   void   pentiumP5PmcGet1
  96.  (
  97.  long long int * pPmc1; /@ performance monitoring counter 1 @/
  98.  )
  99.   void   pentiumP5PmcReset (void)
  100.   void   pentiumP5PmcReset0 (void)
  101.   void   pentiumP5PmcReset1 (void)
  102. .CE
  103. pentiumP5PmcStart0() starts PMC0, and pentiumP5PmcStart1() starts PMC1. 
  104. pentiumP5PmcStop0() stops PMC0, and pentiumP5PmcStop1() stops PMC1.  
  105. pentiumP5PmcGet() gets contents of PMC0 and PMC1.  pentiumP5PmcGet0() gets
  106. contents of PMC0, and pentiumP5PmcGet1() gets contents of PMC1.
  107. pentiumP5PmcReset() resets both PMC0 and PMC1.  pentiumP5PmcReset0() resets
  108. PMC0, and pentiumP5PmcReset1() resets PMC1.
  109. PMC is enabled in sysHwInit().  Selected events in the default configuration
  110. are PMC0 = number of hardware interrupts received and PMC1 = number of 
  111. misaligned data memory references.
  112. .SS "MSR (Model Specific Register)"
  113. The concept of model-specific registers (MSRs) to control hardware functions
  114. in the processor or to monitor processor activity was introduced in the 
  115. PentiumPro processor.  The new registers control the debug extensions, the 
  116. performance counters, the machine-check exception capability, the machine
  117. check architecture, and the MTRRs.  The MSRs can be read and written to using
  118. the RDMSR and WRMSR instructions, respectively.
  119. There are two routines to interface the MSR.  These two routines are:
  120. .CS
  121.   void pentiumMsrGet
  122.        (
  123.        int address, /@ MSR address @/
  124.        long long int * pData /@ MSR data @/
  125.        )
  126.   void pentiumMsrSet
  127.        (
  128.        int address, /@ MSR address @/
  129.        long long int * pData /@ MSR data @/
  130.        )
  131. .CE
  132. pentiumMsrGet() get contents of the specified MSR, and 
  133. pentiumMsrSet() sets value to the specified MSR.
  134. .SS "TSC (Time Stamp Counter)"
  135. The PentiumPro processor provides a 64-bit time-stamp counter that is 
  136. incremented every processor clock cycle.  The counter is incremented even
  137. when the processor is halted by the HLT instruction or the external STPCLK#
  138. pin.  The time-stamp counter is set to 0 following a hardware reset of the
  139. processor.  The RDTSC instruction reads the time stamp counter and is 
  140. guaranteed to return a monotonically increasing unique value whenever 
  141. executed, except for 64-bit counter wraparound.  Intel guarantees, 
  142. architecturally, that the time-stamp counter frequency and configuration will
  143. be such that it will not wraparound within 10 years after being reset to 0.
  144. The period for counter wrap is several thousands of years in the PentiumPro
  145. and Pentium processors.
  146. There are three routines to interface the TSC.  These three routines are:
  147. .CS
  148.   void pentiumTscReset (void)
  149.   void pentiumTscGet32 (void)
  150.   void pentiumTscGet64
  151.        (
  152.        long long int * pTsc /@ TSC @/
  153.        )
  154. .CE
  155. pentiumTscReset() resets the TSC.  pentiumTscGet32() gets the lower half of the
  156. 64Bit TSC, and pentiumTscGet64() gets the entire 64Bit TSC.
  157. Four other routines are provided in this library.  They are:
  158. .CS
  159.   void   pentiumTlbFlush (void)
  160.   void   pentiumSerialize (void)
  161.   STATUS pentiumBts
  162.  (
  163.          char * pFlag                   /@ flag address @/
  164.  )
  165.   STATUS pentiumBtc (pFlag)
  166.  (
  167.          char * pFlag                   /@ flag address @/
  168.  )
  169. .CE
  170. pentiumTlbFlush() flushes TLBs (Translation Lookaside Buffers). 
  171. pentiumSerialize() does serialization by executing CPUID instruction.
  172. pentiumBts() executes an atomic compare-and-exchange instruction to set a bit.
  173. pentiumBtc() executes an atomic compare-and-exchange instruction to clear a bit.
  174. INTERNAL
  175. Many routines in this module doesn't use the "c" frame pointer %ebp@ !
  176. This is only for the benefit of the stacktrace facility to allow it 
  177. to properly trace tasks executing within these routines.
  178. SEE ALSO: 
  179. .I "Pentium, PentiumPro Family Developer's Manual"
  180. */
  181. #define _ASMLANGUAGE
  182. #include "vxWorks.h"
  183. #include "asm.h"
  184. #include "regs.h"
  185. #include "arch/i86/pentiumLib.h"
  186.         .data
  187. .globl  FUNC(copyright_wind_river)
  188. .long   FUNC(copyright_wind_river)
  189. /* internals */
  190. .globl GTEXT(pentiumCr4Get)
  191. .globl GTEXT(pentiumCr4Set)
  192. .globl GTEXT(pentiumP6PmcStart)
  193. .globl GTEXT(pentiumP6PmcStop)
  194. .globl GTEXT(pentiumP6PmcStop1)
  195. .globl GTEXT(pentiumP6PmcGet)
  196. .globl GTEXT(pentiumP6PmcGet0)
  197. .globl GTEXT(pentiumP6PmcGet1)
  198. .globl GTEXT(pentiumP6PmcReset)
  199. .globl GTEXT(pentiumP6PmcReset0)
  200. .globl GTEXT(pentiumP6PmcReset1)
  201.         .globl  GTEXT(pentiumP5PmcStart0)
  202.         .globl  GTEXT(pentiumP5PmcStart1)
  203.         .globl  GTEXT(pentiumP5PmcStop0)
  204.         .globl  GTEXT(pentiumP5PmcStop1)
  205.         .globl  GTEXT(pentiumP5PmcReset)
  206.         .globl  GTEXT(pentiumP5PmcReset0)
  207.         .globl  GTEXT(pentiumP5PmcReset1)
  208.         .globl  GTEXT(pentiumP5PmcGet)
  209.         .globl  GTEXT(pentiumP5PmcGet0)
  210.         .globl  GTEXT(pentiumP5PmcGet1)
  211. .globl GTEXT(pentiumTscGet64)
  212. .globl GTEXT(pentiumTscGet32)
  213. .globl GTEXT(pentiumTscReset)
  214. .globl GTEXT(pentiumMsrGet)
  215. .globl GTEXT(pentiumMsrSet)
  216. .globl GTEXT(pentiumTlbFlush)
  217. .globl GTEXT(pentiumSerialize)
  218. .globl GTEXT(pentiumBts)
  219. .globl GTEXT(pentiumBtc)
  220. .data
  221. .balign 16,0x90
  222. _pmcBusy:
  223. .byte 0x00 /* PMC busy flag, 1 = busy */
  224. _pmc0Busy:
  225.         .byte   0x00                    /* PMC0 busy flag, 1 = busy */
  226. _pmc1Busy:
  227.         .byte   0x00                    /* PMC1 busy flag, 1 = busy */
  228. .text
  229. .balign 16,0x90
  230. /*******************************************************************************
  231. *
  232. * pentiumCr4Get - get contents of CR4 register
  233. *
  234. * SYNOPSIS
  235. * ss
  236. * int pentiumCr4Get (void)
  237. * se
  238. *
  239. * This routine gets the contents of the CR4 register.
  240. *
  241. * RETURNS: Contents of CR4 register.
  242. */
  243. FUNC_LABEL(pentiumCr4Get)
  244. movl %cr4,%eax
  245. ret
  246. /*******************************************************************************
  247. *
  248. * pentiumCr4Set - sets specified value to the CR4 register
  249. *
  250. * SYNOPSIS
  251. * ss
  252. * void pentiumCr4Set (cr4)
  253. *    int cr4; /@ value to write CR4 register @/
  254. * se
  255. * This routine sets a specified value to the CR4 register.
  256. *
  257. *
  258. * RETURNS: N/A
  259. */
  260. .balign 16,0x90
  261. FUNC_LABEL(pentiumCr4Set)
  262. movl SP_ARG1(%esp),%eax
  263. movl %eax,%cr4
  264. ret
  265. /*******************************************************************************
  266. *
  267. * pentiumP6PmcStart - start both PMC0 and PMC1
  268. *
  269. * SYNOPSIS
  270. * ss
  271. * STATUS pentiumP6PmcStart (pmcEvtSel0, pmcEvtSel1)
  272. *     int pmcEvtSel0; /@ Performance Event Select Register 0 @/
  273. *     int pmcEvtSel1; /@ Performance Event Select Register 1 @/
  274. * se
  275. * This routine starts both PMC0 (Performance Monitoring Counter 0) and PMC1
  276. * by writing specified events to Performance Event Select Registers. 
  277. * The first parameter is a content of Performance Event Select Register 0,
  278. * and the second parameter is for the Performance Event Select Register 1.
  279. *
  280. * RETURNS: OK or ERROR if PMC is already started.
  281. */
  282.         .balign 16,0x90
  283. FUNC_LABEL(pentiumP6PmcStart)
  284. xorl %eax,%eax
  285. movl $ TRUE, %edx
  286. lock /* lock the BUS */
  287. cmpxchgb %dl,_pmcBusy /* if (_pmcBusy == 0) */
  288. jnz pentiumP6PmcStart0 /*   {ZF = 1; _pmcBusy = TRUE;} */
  289. movl SP_ARG1(%esp),%eax /* low-order 32 bits */
  290. xorl %edx,%edx /* high-order 32 bits */
  291. movl $ MSR_EVNTSEL0,%ecx /* specify MSR_EVNTSEL0 */
  292. wrmsr /* write %edx:%eax to MSR_EVNTSEL0 */
  293. movl SP_ARG2(%esp),%eax /* low-order 32 bits */
  294. xorl %edx,%edx /* high-order 32 bits */
  295. movl $ MSR_EVNTSEL1,%ecx /* specify MSR_EVNTSEL1 */
  296. wrmsr /* write %edx:%eax to MSR_EVNTSEL1 */
  297. xorl %eax,%eax /* return OK */
  298. ret
  299. pentiumP6PmcStart0:
  300. movl $ ERROR,%eax
  301. ret
  302. /*******************************************************************************
  303. *
  304. * pentiumP6PmcStop - stop both PMC0 and PMC1
  305. *
  306. * SYNOPSIS
  307. * ss
  308. * void pentiumP6PmcStop (void)
  309. * se
  310. * This routine stops both PMC0 (Performance Monitoring Counter 0) and PMC1
  311. * by clearing two Performance Event Select Registers.
  312. *
  313. * RETURNS: N/A
  314. */
  315.         .balign 16,0x90
  316. FUNC_LABEL(pentiumP6PmcStop)
  317. xorl %eax,%eax /* zero low-order 32 bits */
  318. xorl %edx,%edx /* zero high-order 32 bits */
  319. movl $ MSR_EVNTSEL0,%ecx /* specify MSR_EVNTSEL0 */
  320. wrmsr /* write %edx:%eax to MSR_EVNTSEL0 */
  321. movl $ MSR_EVNTSEL1,%ecx /* specify MSR_EVNTSEL1 */
  322. wrmsr /* write %edx:%eax to MSR_EVNTSEL1 */
  323. movl $ TRUE, %eax
  324. xorl %edx,%edx
  325. lock /* lock the BUS */
  326. cmpxchgb %dl,_pmcBusy /* if (_pmcBusy == TRUE) */
  327. ret /*   {ZF = 1; _pmcBusy = 0;} */
  328. /*******************************************************************************
  329. *
  330. * pentiumP6PmcStop1 - stop PMC1
  331. *
  332. * SYNOPSIS
  333. * ss
  334. * void pentiumP6PmcStop1 (void)
  335. * se
  336. * This routine stops only PMC1 (Performance Monitoring Counter 1)
  337. * by clearing the Performance Event Select Register 1.
  338. * Note, clearing the Performance Event Select Register 0 stops both counters,
  339. * PMC0 and PMC1.
  340. *
  341. * RETURNS: N/A
  342. */
  343.         .balign 16,0x90
  344. FUNC_LABEL(pentiumP6PmcStop1)
  345. xorl %eax,%eax /* zero low-order 32 bits */
  346. xorl %edx,%edx /* zero high-order 32 bits */
  347. movl $ MSR_EVNTSEL1,%ecx /* specify MSR_EVNTSEL1 */
  348. wrmsr /* write %edx:%eax to MSR_EVNTSEL1 */
  349. ret
  350. /*******************************************************************************
  351. *
  352. * pentiumP6PmcGet - get the contents of PMC0 and PMC1
  353. *
  354. * SYNOPSIS
  355. * ss
  356. * void pentiumP6PmcGet (pPmc0, pPmc1)
  357. *     long long int * pPmc0; /@ Performance Monitoring Counter 0 @/
  358. *     long long int * pPmc1; /@ Performance Monitoring Counter 1 @/
  359. * se
  360. * This routine gets the contents of both PMC0 (Performance Monitoring Counter 0)
  361. * and PMC1.  The first parameter is a pointer of 64Bit variable to store
  362. * the content of the Counter 0, and the second parameter is for the Counter 1.
  363. *
  364. * RETURNS: N/A
  365. */
  366.         .balign 16,0x90
  367. FUNC_LABEL(pentiumP6PmcGet)
  368. movl $0,%ecx /* specify PMC0 */
  369. rdpmc /* read PMC0 to %edx:%eax */
  370. movl SP_ARG1(%esp),%ecx
  371. movl %eax,(%ecx) /* save low-order 32 bits */
  372. movl %edx,4(%ecx) /* save high-order 32 bits */
  373. movl $1,%ecx /* specify PMC1 */
  374. rdpmc /* read PMC1 to %edx:%eax */
  375. movl SP_ARG2(%esp),%ecx
  376. movl %eax,(%ecx) /* save low-order 32 bits */
  377. movl %edx,4(%ecx) /* save high-order 32 bits */
  378. ret
  379. /*******************************************************************************
  380. *
  381. * pentiumP6PmcGet0 - get the contents of PMC0
  382. *
  383. * SYNOPSIS
  384. * ss
  385. * void pentiumP6PmcGet0 (pPmc0)
  386. *     long long int * pPmc0; /@ Performance Monitoring Counter 0 @/
  387. * se
  388. * This routine gets the contents of PMC0 (Performance Monitoring Counter 0).
  389. * The parameter is a pointer of 64Bit variable to store the content of
  390. * the Counter.
  391. *
  392. * RETURNS: N/A
  393. */
  394.         .balign 16,0x90
  395. FUNC_LABEL(pentiumP6PmcGet0)
  396. movl $0,%ecx /* specify PMC0 */
  397. rdpmc /* read PMC0 to %edx:%eax */
  398. movl SP_ARG1(%esp),%ecx
  399. movl %eax,(%ecx) /* save low-order 32 bits */
  400. movl %edx,4(%ecx) /* save high-order 32 bits */
  401. ret
  402. /*******************************************************************************
  403. *
  404. * pentiumP6PmcGet1 - get the contents of PMC1
  405. *
  406. * SYNOPSIS
  407. * ss
  408. * void pentiumP6PmcGet1 (pPmc1)
  409. *     long long int * pPmc1; /@ Performance Monitoring Counter 1 @/
  410. * se
  411. * This routine gets a content of PMC1 (Performance Monitoring Counter 1).
  412. * Parameter is a pointer of 64Bit variable to store the content of the Counter.
  413. *
  414. * RETURNS: N/A
  415. */
  416.         .balign 16,0x90
  417. FUNC_LABEL(pentiumP6PmcGet1)
  418. movl $1,%ecx /* specify PMC1 */
  419. rdpmc /* read PMC1 to %edx:%eax */
  420. movl SP_ARG1(%esp),%ecx
  421. movl %eax,(%ecx) /* save low-order 32 bits */
  422. movl %edx,4(%ecx) /* save high-order 32 bits */
  423. ret
  424. /*******************************************************************************
  425. *
  426. * pentiumP6PmcReset - reset both PMC0 and PMC1
  427. *
  428. * SYNOPSIS
  429. * ss
  430. * void pentiumP6PmcReset (void)
  431. * se
  432. * This routine resets both PMC0 (Performance Monitoring Counter 0) and PMC1.
  433. *
  434. * RETURNS: N/A
  435. */
  436.         .balign 16,0x90
  437. FUNC_LABEL(pentiumP6PmcReset)
  438. xorl %eax,%eax /* zero low-order 32 bits */
  439. xorl %edx,%edx /* zero high-order 32 bits */
  440. movl $ MSR_PERFCTR0,%ecx /* specify MSR_PERFCTR0 */
  441. wrmsr /* write %edx:%eax to MSR_PERFCTR0 */
  442. movl $ MSR_PERFCTR1,%ecx /* specify MSR_PERFCTR1 */
  443. wrmsr /* write %edx:%eax to MSR_PERFCTR1 */
  444. ret
  445. /*******************************************************************************
  446. *
  447. * pentiumP6PmcReset0 - reset PMC0
  448. *
  449. * SYNOPSIS
  450. * ss
  451. * void pentiumP6PmcReset0 (void)
  452. * se
  453. * This routine resets PMC0 (Performance Monitoring Counter 0).
  454. *
  455. * RETURNS: N/A
  456. */
  457.         .balign 16,0x90
  458. FUNC_LABEL(pentiumP6PmcReset0)
  459. xorl %eax,%eax /* zero low-order 32 bits */
  460. xorl %edx,%edx /* zero high-order 32 bits */
  461. movl $ MSR_PERFCTR0,%ecx /* specify MSR_PERFCTR0 */
  462. wrmsr /* write %edx:%eax to MSR_PERFCTR0 */
  463. ret
  464. /*******************************************************************************
  465. *
  466. * pentiumP6PmcReset1 - reset PMC1
  467. *
  468. * SYNOPSIS
  469. * ss
  470. * void pentiumP6PmcReset1 (void)
  471. * se
  472. * This routine resets PMC1 (Performance Monitoring Counter 1).
  473. *
  474. * RETURNS: N/A
  475. */
  476.         .balign 16,0x90
  477. FUNC_LABEL(pentiumP6PmcReset1)
  478. xorl %eax,%eax /* zero low-order 32 bits */
  479. xorl %edx,%edx /* zero high-order 32 bits */
  480. movl $ MSR_PERFCTR1,%ecx /* specify MSR_PERFCTR1 */
  481. wrmsr /* write %edx:%eax to MSR_PERFCTR1 */
  482. ret
  483. /*******************************************************************************
  484. *
  485. * pentiumP5PmcStart0 - start PMC0
  486. *
  487. * SYNOPSIS
  488. * ss
  489. * STATUS pentiumP5PmcStart0 (pmc0Cesr)
  490. *       int pmc0Cesr;           /@ PMC0 control and event select @/
  491. * se
  492. *
  493. * This routine starts PMC0 (Performance Monitoring Counter 0) 
  494. * by writing specified PMC0 events to Performance Event Select Registers. 
  495. * The only parameter is the content of Performance Event Select Register.
  496. *
  497. * RETURNS: OK or ERROR if PMC0 is already started.
  498. */
  499.         .balign 16,0x90
  500. FUNC_LABEL(pentiumP5PmcStart0)
  501. xorl %eax,%eax
  502. movl $ TRUE, %edx
  503. lock /* lock the BUS */
  504. cmpxchgb %dl,_pmc0Busy /* if (_pmc0Busy == 0) */
  505. jnz pentiumP5PmcStart0L0 /*   {ZF = 1; _pmc0Busy = TRUE;} */
  506. movl $ MSR_CESR,%ecx /* specify MSR_CESR */
  507. rdmsr /* read from MSR_CESR */
  508. andl $ 0xFFFF0000,%eax /* mask out PMC0 bits */
  509. movl SP_ARG1(%esp),%edx /* new PMC0 bits */
  510. andl $ 0x0000FFFF,%edx /* mask out the high 16 bits */
  511. orl %edx,%eax /* merge with orig PMC1 bits */ 
  512. xorl %edx,%edx /* high-order 32 bits */
  513. wrmsr /* write %edx:%eax to MSR_CESR */
  514. xorl %eax,%eax /* return OK */
  515. ret
  516. pentiumP5PmcStart0L0:
  517. movl $ ERROR,%eax
  518. ret
  519. /*******************************************************************************
  520. *
  521. * pentiumP5PmcStart1 - start PMC1
  522. *
  523. * SYNOPSIS
  524. * ss
  525. * STATUS pentiumP5PmcStart1 (pmc1Cesr)
  526. *       int pmc1Cesr;           /@ PMC1 control and event select @/
  527. * se
  528. *
  529. * This routine starts PMC1 (Performance Monitoring Counter 0) 
  530. * by writing specified PMC1 events to Performance Event Select Registers. 
  531. * The only parameter is the content of Performance Event Select Register.
  532. *
  533. * RETURNS: OK or ERROR if PMC1 is already started.
  534. */
  535.         .balign 16,0x90
  536. FUNC_LABEL(pentiumP5PmcStart1)
  537. xorl %eax,%eax
  538. movl $ TRUE, %edx
  539. lock /* lock the BUS */
  540. cmpxchgb %dl,_pmc1Busy /* if (_pmc1Busy == 0) */
  541. jnz pentiumP5PmcStart1L0 /*   {ZF = 1; _pmcBusy = TRUE;} */
  542. movl $ MSR_CESR,%ecx /* specify MSR_CESR */
  543. rdmsr /* read from MSR_CESR */
  544. andl $ 0x0000FFFF,%eax /* mask out PMC1 bits */
  545. movl SP_ARG1(%esp),%edx /* new PMC1 bits */
  546. shll $ 16,%edx      /* shift PMC1 bits to higher 16 bits */
  547. orl %edx,%eax /* merge with orig PMC1 bits */ 
  548. xorl %edx,%edx /* high-order 32 bits */
  549. wrmsr /* write %edx:%eax to MSR_CESR */
  550. xorl %eax,%eax /* return OK */
  551. ret
  552. pentiumP5PmcStart1L0:
  553. movl $ ERROR,%eax
  554. ret
  555. /*******************************************************************************
  556. *
  557. * pentiumP5PmcStop - stop both P5 PMC0 and PMC1
  558. *
  559. * SYNOPSIS
  560. * ss
  561. * void pentiumP5PmcStop (void)
  562. * se
  563. *
  564. * This routine stops both PMC0 (Performance Monitoring Counter 0)
  565. * and PMC1 by clearing two Performance Event Select Registers.
  566. *
  567. * RETURNS: N/A
  568. */
  569.         .balign 16,0x90
  570. FUNC_LABEL(pentiumP5PmcStop)
  571. xorl %eax,%eax /* zero low-order 32 bits */
  572. xorl %edx,%edx /* zero high-order 32 bits */
  573. movl $ MSR_CESR,%ecx
  574. wrmsr /* write %edx:%eax to CESR reg */
  575. movl $ TRUE, %eax
  576. xorl %edx,%edx
  577. lock /* lock the BUS */
  578. cmpxchgb %dl,_pmc0Busy /* if (_pmc0Busy == TRUE) */
  579. /*   {ZF = 1; _pmcBusy = 0;} */
  580. movl $ TRUE, %eax
  581. xorl %edx,%edx
  582. lock /* lock the BUS */
  583. cmpxchgb %dl,_pmc1Busy /* if (_pmc0Busy == TRUE) */
  584. /*   {ZF = 1; _pmcBusy = 0;} */
  585. ret
  586. /*******************************************************************************
  587. *
  588. * pentiumP5PmcStop0 - stop P5 PMC0
  589. *
  590. * SYNOPSIS
  591. * ss
  592. * void pentiumP5PmcStop0 (void)
  593. * se
  594. *
  595. * This routine stops only PMC0 (Performance Monitoring Counter 0)
  596. * by clearing the PMC0 bits of Control and Event Select Register.
  597. *
  598. * RETURNS: N/A
  599. */
  600.         .balign 16,0x90
  601. FUNC_LABEL(pentiumP5PmcStop0)
  602. movl $ MSR_CESR,%ecx /* select MSR_CESR register */
  603. rdmsr
  604. andl $ 0xFFFF0000,%eax /* clear PMC0 bits in MSR_CESR */
  605. xorl %edx,%edx /* zero high-order 32 bits */
  606. wrmsr /* write %edx:%eax to MSR_CESR */
  607. movl $ TRUE, %eax
  608. xorl %edx,%edx
  609. lock /* lock the BUS */
  610. cmpxchgb %dl,_pmc0Busy /* if (_pmc0Busy == TRUE) */
  611. ret
  612. /*******************************************************************************
  613. *
  614. * pentiumP5PmcStop1 - stop P5 PMC1
  615. *
  616. * SYNOPSIS
  617. * ss
  618. * void pentiumP5PmcStop1 (void)
  619. * se
  620. *
  621. * This routine stops only PMC1 (Performance Monitoring Counter 1)
  622. * by clearing the PMC1 bits of Control and Event Select Register.
  623. *
  624. * RETURNS: N/A
  625. */
  626.         .balign 16,0x90
  627. FUNC_LABEL(pentiumP5PmcStop1)
  628. movl $ MSR_CESR,%ecx /* select MSR_CESR register */
  629. rdmsr
  630. andl $ 0x0000FFFF,%eax /* clear PMC1 bits in MSR_CESR */
  631. xorl %edx,%edx /* zero high-order 32 bits */
  632. wrmsr /* write %edx:%eax to MSR_CESR */
  633. movl $ TRUE, %eax
  634. xorl %edx,%edx
  635. lock /* lock the BUS */
  636. cmpxchgb %dl,_pmc1Busy /* if (_pmc1Busy == TRUE) */
  637. ret
  638. /*******************************************************************************
  639. *
  640. * pentiumP5PmcGet - get the contents of P5 PMC0 and PMC1
  641. *
  642. * SYNOPSIS
  643. * ss
  644. * void pentiumP5PmcGet (pPmc0, pPmc1)
  645. *     long long int * pPmc0;            /@ Performance Monitoring Counter 0 @/
  646. *     long long int * pPmc1;            /@ Performance Monitoring Counter 1 @/
  647. * se
  648. *
  649. * This routine gets the contents of both PMC0 (Performance Monitoring Counter 0)
  650. * and PMC1.  The first parameter is a pointer of 64Bit variable to store
  651. * the content of the Counter 0, and the second parameter is for the Counter 1.
  652. *
  653. * RETURNS: N/A
  654. */
  655.         .balign 16,0x90
  656. FUNC_LABEL(pentiumP5PmcGet)
  657. movl $ MSR_CTR0,%ecx /* specify PMC0 */
  658. rdmsr /* read PMC0 to %edx:%eax */
  659. movl SP_ARG1(%esp),%ecx
  660. movl %eax,(%ecx) /* save low-order 32 bits */
  661. movl %edx,4(%ecx) /* save high-order 32 bits */
  662. movl $ MSR_CTR1,%ecx /* specify PMC1 */
  663. rdmsr /* read PMC1 to %edx:%eax */
  664. movl SP_ARG2(%esp),%ecx
  665. movl %eax,(%ecx) /* save low-order 32 bits */
  666. movl %edx,4(%ecx) /* save high-order 32 bits */
  667. ret
  668. /*******************************************************************************
  669. *
  670. * pentiumP5PmcGet0 - get the contents of P5 PMC0
  671. *
  672. * SYNOPSIS
  673. * ss
  674. * void pentiumP5PmcGet0 (pPmc0)
  675. *     long long int * pPmc0;            /@ Performance Monitoring Counter 0 @/
  676. * se
  677. *
  678. * This routine gets the contents of PMC0 (Performance Monitoring Counter 0).
  679. * The parameter is a pointer of 64Bit variable to store the content of
  680. * the Counter.
  681. *
  682. * RETURNS: N/A
  683. */
  684.         .balign 16,0x90
  685. FUNC_LABEL(pentiumP5PmcGet0)
  686. movl $ MSR_CTR0,%ecx /* specify PMC0 */
  687. rdmsr /* read PMC0 to %edx:%eax */
  688. movl SP_ARG1(%esp),%ecx
  689. movl %eax,(%ecx) /* save low-order 32 bits */
  690. movl %edx,4(%ecx) /* save high-order 32 bits */
  691. ret
  692. /*******************************************************************************
  693. *
  694. * pentiumP5PmcGet1 - get the contents of P5 PMC1
  695. *
  696. * SYNOPSIS
  697. * ss
  698. * void pentiumP5PmcGet1 (pPmc1)
  699. *     long long int * pPmc1;            /@ Performance Monitoring Counter 1 @/
  700. * se
  701. *
  702. * This routine gets a content of PMC1 (Performance Monitoring Counter 1).
  703. * Parameter is a pointer of 64Bit variable to store the content of the Counter.
  704. *
  705. * RETURNS: N/A
  706. */
  707.         .balign 16,0x90
  708. FUNC_LABEL(pentiumP5PmcGet1)
  709. movl $ MSR_CTR1,%ecx /* specify PMC1 */
  710. rdmsr /* read PMC1 to %edx:%eax */
  711. movl SP_ARG1(%esp),%ecx
  712. movl %eax,(%ecx) /* save low-order 32 bits */
  713. movl %edx,4(%ecx) /* save high-order 32 bits */
  714. ret
  715. /*******************************************************************************
  716. *
  717. * pentiumP5PmcReset - reset both PMC0 and PMC1
  718. *
  719. * SYNOPSIS
  720. * ss
  721. * void pentiumP5PmcReset (void)
  722. * se
  723. *
  724. * This routine resets both PMC0 (Performance Monitoring Counter 0) and PMC1.
  725. *
  726. * RETURNS: N/A 
  727. */
  728.         .balign 16,0x90
  729. FUNC_LABEL(pentiumP5PmcReset)
  730. xorl %eax,%eax /* zero low-order 32 bits */
  731. xorl %edx,%edx /* zero high-order 32 bits */
  732. movl $ MSR_CTR0,%ecx  /* specify MSR_CTR0 */
  733. wrmsr /* write %edx:%eax to MSR_CTR0 */
  734. movl $ MSR_CTR1,%ecx  /* specify MSR_CRT1 */
  735. wrmsr /* write %edx:%eax to MSR_CTR1 */
  736. ret
  737. /*******************************************************************************
  738. *
  739. * pentiumP5PmcReset0 - reset PMC0
  740. *
  741. * SYNOPSIS
  742. * ss
  743. * void pentiumP5PmcReset0 (void)
  744. * se
  745. *
  746. * This routine resets PMC0 (Performance Monitoring Counter 0).
  747. *
  748. * RETURNS: N/A 
  749. */
  750.         .balign 16,0x90
  751. FUNC_LABEL(pentiumP5PmcReset0)
  752. xorl %eax,%eax /* zero low-order 32 bits */
  753. xorl %edx,%edx /* zero high-order 32 bits */
  754. movl $ MSR_CTR0,%ecx /* specify MSR_CTR0 */
  755. wrmsr /* write %edx:%eax to MSR_CTR1 */
  756. ret
  757. /*******************************************************************************
  758. *
  759. * pentiumP5PmcReset1 - reset PMC1
  760. *
  761. * SYNOPSIS
  762. * ss
  763. * void pentiumP5PmcReset1 (void)
  764. * se
  765. *
  766. * This routine resets PMC1 (Performance Monitoring Counter 1).
  767. *
  768. * RETURNS: N/A
  769. */
  770.         .balign 16,0x90
  771. FUNC_LABEL(pentiumP5PmcReset1)
  772. xorl %eax,%eax /* zero low-order 32 bits */
  773. xorl %edx,%edx /* zero high-order 32 bits */
  774. movl $ MSR_CTR1,%ecx /* specify MSR_CTR1 */
  775. wrmsr /* write %edx:%eax to MSR_CTR1 */
  776. ret
  777. /*******************************************************************************
  778. *
  779. * pentiumTscGet64 - get 64Bit TSC (Timestamp Counter)
  780. *
  781. * SYNOPSIS
  782. * ss
  783. * void pentiumTscGet64 (pTsc)
  784. *     long long int * pTsc; /@ Timestamp Counter @/
  785. * se
  786. * This routine gets 64Bit TSC by RDTSC instruction.
  787. * Parameter is a pointer of 64Bit variable to store the content of the Counter.
  788. *
  789. * RETURNS: N/A
  790. */
  791.         .balign 16,0x90
  792. FUNC_LABEL(pentiumTscGet64)
  793. movl SP_ARG1(%esp),%ecx
  794. rdtsc /* read TSC to %edx:%eax */
  795. movl %eax,(%ecx) /* save low-order 32 bits */
  796. movl %edx,4(%ecx) /* save high-order 32 bits */
  797. ret
  798. /*******************************************************************************
  799. *
  800. * pentiumTscGet32 - get the lower half of the 64Bit TSC (Timestamp Counter)
  801. *
  802. * SYNOPSIS
  803. * ss
  804. * UINT32 pentiumTscGet32 (void)
  805. * se
  806. * This routine gets a lower half of the 64Bit TSC by RDTSC instruction.
  807. * RDTSC instruction saves the lower 32Bit in EAX register, so this routine
  808. * simply returns after executing RDTSC instruction.
  809. *
  810. * RETURNS: Lower half of the 64Bit TSC (Timestamp Counter)
  811. */
  812.         .balign 16,0x90
  813. FUNC_LABEL(pentiumTscGet32)
  814. rdtsc /* read TSC to %edx:%eax */
  815. ret
  816. /*******************************************************************************
  817. *
  818. * pentiumTscReset - reset the TSC (Timestamp Counter)
  819. *
  820. * SYNOPSIS
  821. * ss
  822. * void pentiumTscReset (void)
  823. * se
  824. * This routine resets the TSC by writing zero to the TSC with WRMSR
  825. * instruction.  
  826. *
  827. * RETURNS: N/A
  828. */
  829.         .balign 16,0x90
  830. FUNC_LABEL(pentiumTscReset)
  831. xorl %eax,%eax /* zero low-order 32 bits */
  832. xorl %edx,%edx /* zero high-order 32 bits */
  833. movl $ MSR_TSC,%ecx /* specify MSR_TSC */
  834. wrmsr /* write %edx:%eax to TSC */
  835. ret
  836. /*******************************************************************************
  837. *
  838. * pentiumMsrGet - get the contents of the specified MSR (Model Specific Register)
  839. *
  840. * SYNOPSIS
  841. * ss
  842. * void pentiumMsrGet (addr, pData)
  843. *     int addr; /@ MSR address @/
  844. *     long long int * pData; /@ MSR data @/
  845. * se
  846. * This routine gets the contents of the specified MSR.  The first parameter is
  847. * an address of the MSR.  The second parameter is a pointer of 64Bit variable.
  848. *
  849. * RETURNS: N/A
  850. */
  851.         .balign 16,0x90
  852. FUNC_LABEL(pentiumMsrGet)
  853. movl SP_ARG1(%esp),%ecx /* specify MSR to read */
  854. rdmsr /* read the MSR to %edx:%eax */
  855. movl SP_ARG2(%esp),%ecx
  856. movl %eax,(%ecx) /* save low-order 32 bits */
  857. movl %edx,4(%ecx) /* save high-order 32 bits */
  858. ret
  859. /*******************************************************************************
  860. *
  861. * pentiumMsrSet - set a value to the specified MSR (Model Specific Registers)
  862. *
  863. * SYNOPSIS
  864. * ss
  865. * void pentiumMsrSet (addr, pData)
  866. *     int addr; /@ MSR address @/
  867. *     long long int * pData; /@ MSR data @/
  868. * se
  869. * This routine sets a value to a specified MSR.  The first parameter is an
  870. * address of the MSR.  The second parameter is a pointer of 64Bit variable.
  871. *
  872. * RETURNS: N/A
  873. */
  874.         .balign 16,0x90
  875. FUNC_LABEL(pentiumMsrSet)
  876. movl SP_ARG2(%esp),%ecx
  877. movl (%ecx),%eax /* low-order 32 bits */
  878. movl 4(%ecx),%edx /* high-order 32 bits */
  879. movl SP_ARG1(%esp),%ecx /* specify MSR to read */
  880. wrmsr /* write %edx:%eax to the MSR */
  881. ret
  882. /*******************************************************************************
  883. *
  884. * pentiumTlbFlush - flush TLBs (Translation Lookaside Buffers)
  885. *
  886. * SYNOPSIS
  887. * ss
  888. * void pentiumTlbFlush (void)
  889. * se
  890. * This routine flushes TLBs by loading the CR3 register.
  891. * All of the TLBs are automatically invalidated any time the CR3 register is
  892. * loaded.  The page global enable (PGE) flag in register CR4 and the global
  893. * flag in a page-directory or page-table entry can be used to frequently used
  894. * pages from being automatically invalidated in the TLBs on a load of CR3
  895. * register.  The only way to deterministically invalidate global page entries
  896. * is to clear the PGE flag and then invalidate the TLBs.
  897. *
  898. * RETURNS: N/A
  899. */
  900.         .balign 16,0x90
  901. FUNC_LABEL(pentiumTlbFlush)
  902. movl    %cr3,%eax
  903. movl    %eax,%cr3 /* flush the TLB */
  904. jmp     pentiumTlbFlush0 /* flush the prefetch queue */
  905. pentiumTlbFlush0:
  906. ret
  907. /*******************************************************************************
  908. *
  909. * pentiumSerialize - execute a serializing instruction CPUID
  910. *
  911. * SYNOPSIS
  912. * ss
  913. * void pentiumSerialize (void)
  914. * se
  915. * This routine executes a serializing instruction CPUID.
  916. * Serialization means that all modifications to flags, registers, and memory
  917. * by previous instructions are completed before the next instruction is fetched
  918. * and executed and all buffered writes have drained to memory.
  919. *
  920. * RETURNS: N/A
  921. */
  922.         .balign 16,0x90
  923. FUNC_LABEL(pentiumSerialize)
  924. pushl %ebx /* save ebx which is used by cpuid */
  925. cpuid /* serializing instruction */
  926. popl %ebx /* restore ebx */
  927. ret
  928. /*******************************************************************************
  929. *
  930. * pentiumBts - execute atomic compare-and-exchange instruction to set a bit
  931. *
  932. * SYNOPSIS
  933. * ss
  934. * STATUS pentiumBts (pFlag)
  935. *     char * pFlag; /@ flag address @/
  936. * se
  937. * This routine compares a byte specified by the first parameter with 0.
  938. * If it is 0, it changes it to TRUE and returns OK.
  939. * If it is not 0, it returns ERROR.  LOCK and CMPXCHGB are used to get 
  940. * the atomic memory access.
  941. *
  942. * RETURNS: OK or ERROR if the specified flag is not zero.
  943. */
  944.         .balign 16,0x90
  945. FUNC_LABEL(pentiumBts)
  946. movl SP_ARG1(%esp),%ecx
  947. xorl %eax,%eax
  948. movl $ TRUE,%edx
  949. lock /* lock the BUS */
  950. cmpxchgb %dl,(%ecx) /* if (flag == 0) */
  951. jnz pentiumBts0 /*   {ZF = 1; flag = TRUE;} */
  952. ret
  953. pentiumBts0:
  954. movl $ ERROR,%eax
  955. ret
  956. /*******************************************************************************
  957. *
  958. * pentiumBtc - execute atomic compare-and-exchange instruction to clear a bit
  959. *
  960. * SYNOPSIS
  961. * ss
  962. * STATUS pentiumBtc (pFlag)
  963. *     char * pFlag; /@ flag address @/
  964. * se
  965. * This routine compares a byte specified by the first parameter with TRUE.
  966. * If it is TRUE, it changes it to 0 and returns OK.
  967. * If it is not TRUE, it returns ERROR.  LOCK and CMPXCHGB are used to get 
  968. * the atomic memory access.
  969. *
  970. * RETURNS: OK or ERROR if the specified flag is not TRUE
  971. */
  972.         .balign 16,0x90
  973. FUNC_LABEL(pentiumBtc)
  974. movl SP_ARG1(%esp),%ecx
  975. movl $ TRUE,%eax
  976. xorl %edx,%edx
  977. lock /* lock the BUS */
  978. cmpxchgb %dl,(%ecx) /* if (flag == TRUE) */
  979. jnz pentiumBtc0 /*   {ZF = 1; flag = 0;} */
  980. xorl %eax,%eax
  981. ret
  982. pentiumBtc0:
  983. movl $ ERROR,%eax
  984. ret