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

VxWorks

开发平台:

C/C++

  1. /* pentiumLib.c - Pentium and Pentium[234] library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01f,20nov01,hdn  doc clean up for 5.5
  8. 01e,01nov01,hdn  added pentiumMsrInit() and pentiumMcaEnable().
  9. 01d,21aug01,hdn  added P5/P6 PMC routines from T31 ver 01e
  10.  fixed a bug in pentiumMtrr[GS]et() (spr 68103)
  11. 01c,24mar99,jdi  doc: added basic formatting cmds, particularly .CS/.CE
  12.  to set off code snippets as per standard practice.
  13. 01b,17apr98,hdn  fixed typo.
  14. 01b,17apr98,hdn  added documentation.
  15. 01a,09jul97,hdn  written.
  16. */
  17. /*
  18. DESCRIPTION
  19. This library provides Pentium and Pentium[234] specific routines. 
  20. .SS "MTRR (Memory Type Range Register)"
  21. MTRR (Memory Type Range Register) are a new feature introduced in the 
  22. P6 family processor that allow the processor to optimize memory operations
  23. for different types of memory, such as RAM, ROM, frame buffer memory, and
  24. memory-mapped IO.  MTRRs configure an internal map of how physical address 
  25. ranges are mapped to various types of memory.  The processor uses this internal
  26. map to determine the cacheability of various physical memory locations and the
  27. optimal method of accessing memory locations.  For example, if a memory
  28. location is specified in an MTRR as write-through memory, the processor handles
  29. accesses to this location as follows.  It reads data from that location in 
  30. lines and caches the read data or maps all writes to that location to the bus
  31. and updates the cache to maintain cache coherency.  In mapping the physical
  32. address space with MTRRs, the processor recognizes five types of memory:
  33. uncacheable (UC), write-combining (WC), write-through (WT),
  34. write-protected (WP), and write-back (WB).
  35. There is one table - sysMtrr[] in sysLib.c - and four routines to interface
  36. the MTRR.  These four routines are:
  37. .CS
  38.   void pentiumMtrrEnable (void)
  39.   void pentiumMtrrDisable (void)
  40.   STATUS pentiumMtrrGet
  41.       (
  42.       MTRR * pMtrr /@ MTRR table @/
  43.       )
  44.   STATUS pentiumMtrrSet (void)
  45.       (
  46.       MTRR * pMtrr /@ MTRR table @/
  47.       )
  48. .CE
  49. pentiumMtrrEnable() enables MTRR, pentiumMtrrDisable() disables MTRR.
  50. pentiumMtrrGet() gets MTRRs to the specified MTRR table.
  51. pentiumMtrrGet() sets MTRRs from the specified MTRR table.
  52. The MTRR table is defined as follows:
  53. .CS
  54. typedef struct mtrr_fix         /@ MTRR - fixed range register @/
  55.     {
  56.     char type[8]; /@ address range: [0]=0-7 ... [7]=56-63 @/
  57.     } MTRR_FIX;
  58. typedef struct mtrr_var         /@ MTRR - variable range register @/
  59.     {
  60.     long long int base; /@ base register @/
  61.     long long int mask; /@ mask register @/
  62.     } MTRR_VAR;
  63. typedef struct mtrr             /@ MTRR @/
  64.     {
  65.     int cap[2];                 /@ MTRR cap register @/
  66.     int deftype[2];             /@ MTRR defType register @/
  67.     MTRR_FIX fix[11];           /@ MTRR fixed range registers @/
  68.     MTRR_VAR var[8];            /@ MTRR variable range registers @/
  69.     } MTRR;
  70. .CE
  71. Fixed Range Register's type array can be one of following memory types.
  72. MTRR_UC (uncacheable), MTRR_WC (write-combining), 
  73. MTRR_WT (write-through), MTRR_WP (write-protected), and MTRR_WB (write-back).
  74. MTRR is enabled in sysHwInit().
  75. .SS "PMC (Performance Monitoring Counters)"
  76. The P5 and P6 family of processors has two performance-monitoring counters
  77. for use in monitoring internal hardware operations. These counters are
  78. duration or event counters that can be programmed to count any of approximately
  79. 100 different types of events, such as the number of instructions decoded,
  80. number of interrupts received, or number of cache loads. However, the set of
  81. events can be counted with PMC is different in the P5 and P6 family of
  82. processors; and the locations and bit difinitions of the related counter and
  83. control registers are also different. So there are two set of PMC routines,
  84. one for P6 family and one for P5 family respectively in pentiumALib. For
  85. convenience, the PMC routines here are acting as wrappers to those routines
  86. in pentiumALib. They will call the P5 or P6 routine depending on the processor 
  87. type.
  88. There are twelve routines to interface the PMC.  These twelve routines are:
  89. .CS
  90.   STATUS pentiumPmcStart
  91.          (
  92.          int pmcEvtSel0;        /@ performance event select register 0 @/
  93.          int pmcEvtSel1;        /@ performance event select register 1 @/
  94.          )
  95.   STATUS pentiumPmcStart0
  96.          (
  97.          int pmcEvtSel0;        /@ performance event select register 0 @/
  98.          )
  99.   STATUS pentiumPmcStart1
  100.          (
  101.          int pmcEvtSel1;        /@ performance event select register 1 @/
  102.          )
  103.   void   pentiumPmcStop (void)
  104.   void   pentiumPmcStop0 (void)
  105.   void   pentiumPmcStop1 (void)
  106.   void   pentiumPmcGet
  107.          (
  108.          long long int * pPmc0; /@ performance monitoring counter 0 @/
  109.          long long int * pPmc1; /@ performance monitoring counter 1 @/
  110.          )
  111.   void   pentiumPmcGet0
  112.          (
  113.          long long int * pPmc0; /@ performance monitoring counter 0 @/
  114.          )
  115.   void   pentiumPmcGet1
  116.          (
  117.          long long int * pPmc1; /@ performance monitoring counter 1 @/
  118.          )
  119.   void   pentiumPmcReset (void)
  120.   void   pentiumPmcReset0 (void)
  121.   void   pentiumPmcReset1 (void)
  122. .CE
  123. pentiumPmcStart() starts both PMC0 and PMC1. pentiumPmcStart0() starts PMC0,
  124. and pentiumPmcStart1() starts PMC1.
  125. pentiumPmcStop() stops both PMC0 and PMC1. pentiumPmcStop0() stops PMC0, 
  126. and pentiumPmcStop1() stops PMC1.
  127. pentiumPmcGet() gets contents of PMC0 and PMC1.  pentiumPmcGet0() gets
  128. contents of PMC0, and pentiumPmcGet1() gets contents of PMC1.
  129. pentiumPmcReset() resets both PMC0 and PMC1.  pentiumPmcReset0() resets
  130. PMC0, and pentiumPmcReset1() resets PMC1.
  131. PMC is enabled in sysHwInit().  Selected events in the default configuration
  132. are PMC0 = number of hardware interrupts received and PMC1 = number of
  133. misaligned data memory references.
  134. .SS "MSR (Model Specific Registers)"
  135. The P5(Pentium), P6(PentiumPro, II, III), and P7(Pentium4) family processors
  136. contain a model-specific registers (MSRs).  These registers are implement-
  137. ation specific.  They are provided to control a variety of hardware and 
  138. software related features including the performance monitoring, the debug
  139. extensions, the machine check architecture, etc.
  140. There is one routine - pentiumMsrInit() - to initialize all the MSRs.
  141. This routine initializes all the MSRs in the processor and works on either
  142. P5, P6 or P7 family processors.
  143. .SS "MCA (Machine Check Architecture)"
  144. The P5(Pentium), P6(PentiumPro, II, III), and P7(Pentium4) family processors
  145. have a machine-check architecture that provides a mechanism for detecting 
  146. and reporting hardware (machine) errors, such as system bus errors, ECC
  147. errors, parity errors, cache errors and TLB errors.  It consists of a set
  148. of model-specific registers (MSRs) that are used to set up machine checking 
  149. and additional banks of MSRs for recording errors that are detected.
  150. The processor signals the detection of a machine-check error by generating
  151. a machine-check exception, which an abort class exception.  The implement-
  152. ation of the machine-check architecture, does not ordinarily permit the 
  153. processor to be restarted reliably after generating a machine-check 
  154. exception.  However, the machine-check exception handler can collect
  155. information about the machine-check error from the machine-check MSRs.
  156. There is one routine - pentiumMcaEnable() - to enable or disable the MCA.
  157. The routine enables or disables 1) the Machine Check Architecture and its 
  158. Error Reporting register banks 2) the Machine Check Exception by toggling
  159. the MCE bit in the CR4.  This routine works on either P5, P6 or P7 family.
  160. SEE ALSO:
  161. .I PentiumALib, "Pentium, Pentium[234] Family Developer's Manual"
  162. */
  163. /* includes */
  164. #include "vxWorks.h"
  165. #include "regs.h"
  166. #include "arch/i86/pentiumLib.h"
  167. #include "vxLib.h"
  168. #include "intLib.h"
  169. #include "cacheLib.h"
  170. /* defines */
  171. #define IA32_MISC_ENABLE_DEFAULT (MSC_FAST_STRING_ENABLE | 
  172.  MSC_THERMAL_MON_ENABLE)
  173. #define MSR_ROB_CR_BKUPTMPDR6_DEFAULT 0x4
  174. /* externals */
  175. IMPORT CPUID sysCpuId;
  176. IMPORT int sysProcessor;
  177. /* globals */
  178. PENTIUM_MSR pentiumMsrP5[] = {
  179.     {MSR_P5_MC_ADDR, "P5_MC_ADDR"},
  180.     {MSR_P5_MC_TYPE, "P5_MC_TYPE"},
  181.     {MSR_TSC, "TSC"},
  182.     {MSR_CESR, "CESR"},
  183.     {MSR_CTR0, "CTR0"},
  184.     {MSR_CTR1, "CTR1"},
  185.     };
  186. INT32 pentiumMsrP5NumEnt = NELEMENTS (pentiumMsrP5);
  187. PENTIUM_MSR pentiumMsrP6[] = {
  188.     {MSR_P5_MC_ADDR, "P5_MC_ADDR"},
  189.     {MSR_P5_MC_TYPE, "P5_MC_TYPE"},
  190.     {MSR_TSC, "TSC"},
  191.     {IA32_PLATFORM_ID, "IA32_PLATFORM_ID"},
  192.     {MSR_APICBASE, "APICBASE"},
  193.     {MSR_EBL_CR_POWERON, "EBL_CR_POWERON"},
  194.     {MSR_TEST_CTL, "TEST_CTL"},
  195.     /* RW triggers the loading of the microcode update.
  196.     {MSR_BIOS_UPDT_TRIG, "BIOS_UPDT_TRIG"},
  197.     */
  198.     {MSR_BBL_CR_D0, "BBL_CR_D0"},
  199.     {MSR_BBL_CR_D1, "BBL_CR_D1"},
  200.     {MSR_BBL_CR_D2, "BBL_CR_D2"},
  201.     {MSR_BIOS_SIGN, "BIOS_SIGN"},
  202.     {MSR_PERFCTR0, "PERFCTR0"},
  203.     {MSR_PERFCTR1, "PERFCTR1"},
  204.     {MSR_MTRR_CAP, "MTRR_CAP"},
  205.     {MSR_BBL_CR_ADDR, "BBL_CR_ADDR"},
  206.     {MSR_BBL_CR_DECC, "BBL_CR_DECC"},
  207.     {MSR_BBL_CR_CTL, "BBL_CR_CTL"},
  208.     /* write only with Data=0, reading generates GPF exception.
  209.     {MSR_BBL_CR_TRIG, "BBL_CR_TRIG"},
  210.     */
  211.     {MSR_BBL_CR_BUSY, "BBL_CR_BUSY"},
  212.     {MSR_BBL_CR_CTL3, "BBL_CR_CTL3"},
  213.     {MSR_SYSENTER_CS, "SYSENTER_CS"},
  214.     {MSR_SYSENTER_ESP, "SYSENTER_ESP"},
  215.     {MSR_SYSENTER_EIP, "SYSENTER_EIP"},
  216.     {MSR_MCG_CAP, "MCG_CAP"},
  217.     {MSR_MCG_STATUS, "MCG_STATUS"},
  218.     /* generate GPF exception if not present.
  219.     {MSR_MCG_CTL, "MCG_CTL"},
  220.     */
  221.     {MSR_EVNTSEL0, "EVNTSEL0"},
  222.     {MSR_EVNTSEL1, "EVNTSEL1"},
  223.     {MSR_DEBUGCTLMSR, "DEBUGCTLMSR"},
  224.     {MSR_LASTBRANCH_FROMIP, "LASTBRANCH_FROMIP"},
  225.     {MSR_LASTBRANCH_TOIP, "LASTBRANCH_TOIP"},
  226.     {MSR_LASTINT_FROMIP, "LASTINT_FROMIP"},
  227.     {MSR_LASTINT_TOIP, "LASTINT_TOIP"},
  228.     {MSR_ROB_CR_BKUPTMPDR6, "ROB_CR_BKUPTMPDR6"},
  229.     {MSR_MTRR_PHYS_BASE0, "MTRR_PHYS_BASE0"},
  230.     {MSR_MTRR_PHYS_MASK0, "MTRR_PHYS_MASK0"},
  231.     {MSR_MTRR_PHYS_BASE1, "MTRR_PHYS_BASE1"},
  232.     {MSR_MTRR_PHYS_MASK1, "MTRR_PHYS_MASK1"},
  233.     {MSR_MTRR_PHYS_BASE2, "MTRR_PHYS_BASE2"},
  234.     {MSR_MTRR_PHYS_MASK2, "MTRR_PHYS_MASK2"},
  235.     {MSR_MTRR_PHYS_BASE3, "MTRR_PHYS_BASE3"},
  236.     {MSR_MTRR_PHYS_MASK3, "MTRR_PHYS_MASK3"},
  237.     {MSR_MTRR_PHYS_BASE4, "MTRR_PHYS_BASE4"},
  238.     {MSR_MTRR_PHYS_MASK4, "MTRR_PHYS_MASK4"},
  239.     {MSR_MTRR_PHYS_BASE5, "MTRR_PHYS_BASE5"},
  240.     {MSR_MTRR_PHYS_MASK5, "MTRR_PHYS_MASK5"},
  241.     {MSR_MTRR_PHYS_BASE6, "MTRR_PHYS_BASE6"},
  242.     {MSR_MTRR_PHYS_MASK6, "MTRR_PHYS_MASK6"},
  243.     {MSR_MTRR_PHYS_BASE7, "MTRR_PHYS_BASE7"},
  244.     {MSR_MTRR_PHYS_MASK7, "MTRR_PHYS_MASK7"},
  245.     {MSR_MTRR_FIX_00000, "MTRR_FIX_00000"},
  246.     {MSR_MTRR_FIX_80000, "MTRR_FIX_80000"},
  247.     {MSR_MTRR_FIX_A0000, "MTRR_FIX_A0000"},
  248.     {MSR_MTRR_FIX_C0000, "MTRR_FIX_C0000"},
  249.     {MSR_MTRR_FIX_C8000, "MTRR_FIX_C8000"},
  250.     {MSR_MTRR_FIX_D0000, "MTRR_FIX_D0000"},
  251.     {MSR_MTRR_FIX_D8000, "MTRR_FIX_D8000"},
  252.     {MSR_MTRR_FIX_E0000, "MTRR_FIX_E0000"},
  253.     {MSR_MTRR_FIX_E8000, "MTRR_FIX_E8000"},
  254.     {MSR_MTRR_FIX_F0000, "MTRR_FIX_F0000"},
  255.     {MSR_MTRR_FIX_F8000, "MTRR_FIX_F8000"},
  256.     {MSR_MTRR_DEFTYPE, "MTRR_DEFTYPE"},
  257.     /* use pentiumMcaEnable() or pentiumMcaShow()
  258.     {MSR_MC0_CTL, "MC0_CTL"},
  259.     {MSR_MC0_STATUS, "MC0_STATUS"},
  260.     {MSR_MC0_ADDR, "MC0_ADDR"},
  261.     {MSR_MC0_MISC, "MC0_MISC"},
  262.     {MSR_MC1_CTL, "MC1_CTL"},
  263.     {MSR_MC1_STATUS, "MC1_STATUS"},
  264.     {MSR_MC1_ADDR, "MC1_ADDR"},
  265.     {MSR_MC1_MISC, "MC1_MISC"},
  266.     {MSR_MC2_CTL, "MC2_CTL"},
  267.     {MSR_MC2_STATUS, "MC2_STATUS"},
  268.     {MSR_MC2_ADDR, "MC2_ADDR"},
  269.     {MSR_MC2_MISC, "MC2_MISC"},
  270.     {MSR_MC4_CTL, "MC4_CTL"},
  271.     {MSR_MC4_STATUS, "MC4_STATUS"},
  272.     {MSR_MC4_ADDR, "MC4_ADDR"},
  273.     {MSR_MC4_MISC, "MC4_MISC"},
  274.     {MSR_MC3_CTL, "MC3_CTL"},
  275.     {MSR_MC3_STATUS, "MC3_STATUS"},
  276.     {MSR_MC3_ADDR, "MC3_ADDR"},
  277.     {MSR_MC3_MISC, "MC3_MISC"},
  278.     */
  279.     };
  280. INT32 pentiumMsrP6NumEnt = NELEMENTS (pentiumMsrP6);
  281. PENTIUM_MSR pentiumMsrP7[] = {
  282.     {IA32_P5_MC_ADDR, "IA32_P5_MC_ADDR"},
  283.     {IA32_P5_MC_TYPE, "IA32_P5_MC_TYPE"},
  284.     {IA32_TIME_STAMP_COUNTER, "IA32_TIME_STAMP_COUNTER"},
  285.     {IA32_PLATFORM_ID, "IA32_PLATFORM_ID"},
  286.     {IA32_APIC_BASE, "IA32_APIC_BASE"},
  287.     {MSR_EBC_HARD_POWERON, "EBC_HARD_POWERON"},
  288.     {MSR_EBC_SOFT_POWERON, "EBC_SOFT_POWERON"},
  289.     {MSR_EBC_FREQUENCY_ID, "EBC_FREQUENCY_ID"},
  290.     /* RW triggers the loading of the microcode update.
  291.     {IA32_BIOS_UPDT_TRIG, "IA32_BIOS_UPDT_TRIG"},
  292.      */
  293.     {IA32_BIOS_SIGN_ID, "IA32_BIOS_SIGN_ID"},
  294.     {IA32_MTRRCAP, "IA32_MTRRCAP"},
  295.     {IA32_MISC_CTL, "IA32_MISC_CTL"},
  296.     {IA32_SYSENTER_CS, "IA32_SYSENTER_CS"},
  297.     {IA32_SYSENTER_ESP, "IA32_SYSENTER_ESP"},
  298.     {IA32_SYSENTER_EIP, "IA32_SYSENTER_EIP"},
  299.     {IA32_MCG_CAP, "IA32_MCG_CAP"},
  300.     {IA32_MCG_STATUS, "IA32_MCG_STATUS"},
  301.     /* generate GPF exception if not present.
  302.     {IA32_MCG_CTL, "IA32_MCG_CTL"},
  303.     {IA32_MCG_EAX, "IA32_MCG_EAX"},
  304.     {IA32_MCG_EBX, "IA32_MCG_EBX"},
  305.     {IA32_MCG_ECX, "IA32_MCG_ECX"},
  306.     {IA32_MCG_EDX, "IA32_MCG_EDX"},
  307.     {IA32_MCG_ESI, "IA32_MCG_ESI"},
  308.     {IA32_MCG_EDI, "IA32_MCG_EDI"},
  309.     {IA32_MCG_EBP, "IA32_MCG_EBP"},
  310.     {IA32_MCG_ESP, "IA32_MCG_ESP"},
  311.     {IA32_MCG_EFLAGS, "IA32_MCG_EFLAGS"},
  312.     {IA32_MCG_EIP, "IA32_MCG_EIP"},
  313.     {IA32_MCG_MISC, "IA32_MCG_MISC"},
  314.      */
  315.     {IA32_THERM_CONTROL, "IA32_THERM_CONTROL"},
  316.     {IA32_THERM_INTERRUPT, "IA32_THERM_INTERRUPT"},
  317.     {IA32_THERM_STATUS, "IA32_THERM_STATUS"},
  318.     {IA32_MISC_ENABLE, "IA32_MISC_ENABLE"},
  319.     {MSR_LER_FROM_LIP, "LER_FROM_LIP"},
  320.     {MSR_LER_TO_LIP, "LER_TO_LIP"},
  321.     {IA32_DEBUGCTL, "IA32_DEBUGCTL"},
  322.     {MSR_LASTBRANCH_TOS, "LASTBRANCH_TOS"},
  323.     {MSR_LASTBRANCH_0, "LASTBRANCH_0"},
  324.     {MSR_LASTBRANCH_1, "LASTBRANCH_1"},
  325.     {MSR_LASTBRANCH_2, "LASTBRANCH_2"},
  326.     {MSR_LASTBRANCH_3, "LASTBRANCH_3"},
  327.     {IA32_MTRR_PHYSBASE0, "IA32_MTRR_PHYSBASE0"},
  328.     {IA32_MTRR_PHYSMASK0, "IA32_MTRR_PHYSMASK0"},
  329.     {IA32_MTRR_PHYSBASE1, "IA32_MTRR_PHYSBASE1"},
  330.     {IA32_MTRR_PHYSMASK1, "IA32_MTRR_PHYSMASK1"},
  331.     {IA32_MTRR_PHYSBASE2, "IA32_MTRR_PHYSBASE2"},
  332.     {IA32_MTRR_PHYSMASK2, "IA32_MTRR_PHYSMASK2"},
  333.     {IA32_MTRR_PHYSBASE3, "IA32_MTRR_PHYSBASE3"},
  334.     {IA32_MTRR_PHYSMASK3, "IA32_MTRR_PHYSMASK3"},
  335.     {IA32_MTRR_PHYSBASE4, "IA32_MTRR_PHYSBASE4"},
  336.     {IA32_MTRR_PHYSMASK4, "IA32_MTRR_PHYSMASK4"},
  337.     {IA32_MTRR_PHYSBASE5, "IA32_MTRR_PHYSBASE5"},
  338.     {IA32_MTRR_PHYSMASK5, "IA32_MTRR_PHYSMASK5"},
  339.     {IA32_MTRR_PHYSBASE6, "IA32_MTRR_PHYSBASE6"},
  340.     {IA32_MTRR_PHYSMASK6, "IA32_MTRR_PHYSMASK6"},
  341.     {IA32_MTRR_PHYSBASE7, "IA32_MTRR_PHYSBASE7"},
  342.     {IA32_MTRR_PHYSMASK7, "IA32_MTRR_PHYSMASK7"},
  343.     {IA32_MTRR_FIX64K_00000, "IA32_MTRR_FIX64K_00000"},
  344.     {IA32_MTRR_FIX16K_80000, "IA32_MTRR_FIX16K_80000"},
  345.     {IA32_MTRR_FIX16K_A0000, "IA32_MTRR_FIX16K_A0000"},
  346.     {IA32_MTRR_FIX4K_C0000, "IA32_MTRR_FIX4K_C0000"},
  347.     {IA32_MTRR_FIX4K_C8000, "IA32_MTRR_FIX4K_C8000"},
  348.     {IA32_MTRR_FIX4K_D0000, "IA32_MTRR_FIX4K_D0000"},
  349.     {IA32_MTRR_FIX4K_D8000, "IA32_MTRR_FIX4K_D8000"},
  350.     {IA32_MTRR_FIX4K_E0000, "IA32_MTRR_FIX4K_E0000"},
  351.     {IA32_MTRR_FIX4K_E8000, "IA32_MTRR_FIX4K_E8000"},
  352.     {IA32_MTRR_FIX4K_F8000, "IA32_MTRR_FIX4K_F8000"},
  353.     {IA32_CR_PAT, "IA32_CR_PAT"},
  354.     {IA32_MTRR_DEF_TYPE, "IA32_MTRR_DEF_TYPE"},
  355.     {MSR_BPU_COUNTER0, "BPU_COUNTER0"},
  356.     {MSR_BPU_COUNTER1, "BPU_COUNTER1"},
  357.     {MSR_BPU_COUNTER2, "BPU_COUNTER2"},
  358.     {MSR_BPU_COUNTER3, "BPU_COUNTER3"},
  359.     {MSR_MS_COUNTER0, "MS_COUNTER0"},
  360.     {MSR_MS_COUNTER1, "MS_COUNTER1"},
  361.     {MSR_MS_COUNTER2, "MS_COUNTER2"},
  362.     {MSR_MS_COUNTER3, "MS_COUNTER3"},
  363.     {MSR_FLAME_COUNTER0, "FLAME_COUNTER0"},
  364.     {MSR_FLAME_COUNTER1, "FLAME_COUNTER1"},
  365.     {MSR_FLAME_COUNTER2, "FLAME_COUNTER2"},
  366.     {MSR_FLAME_COUNTER3, "FLAME_COUNTER3"},
  367.     {MSR_IQ_COUNTER0, "IQ_COUNTER0"},
  368.     {MSR_IQ_COUNTER1, "IQ_COUNTER1"},
  369.     {MSR_IQ_COUNTER2, "IQ_COUNTER2"},
  370.     {MSR_IQ_COUNTER3, "IQ_COUNTER3"},
  371.     {MSR_IQ_COUNTER4, "IQ_COUNTER4"},
  372.     {MSR_IQ_COUNTER5, "IQ_COUNTER5"},
  373.     {MSR_BPU_CCCR0, "BPU_CCCR0"},
  374.     {MSR_BPU_CCCR1, "BPU_CCCR1"},
  375.     {MSR_BPU_CCCR2, "BPU_CCCR2"},
  376.     {MSR_BPU_CCCR3, "BPU_CCCR3"},
  377.     {MSR_MS_CCCR0, "MS_CCCR0"},
  378.     {MSR_MS_CCCR1, "MS_CCCR1"},
  379.     {MSR_MS_CCCR2, "MS_CCCR2"},
  380.     {MSR_MS_CCCR3, "MS_CCCR3"},
  381.     {MSR_FLAME_CCCR0, "FLAME_CCCR0"},
  382.     {MSR_FLAME_CCCR1, "FLAME_CCCR1"},
  383.     {MSR_FLAME_CCCR2, "FLAME_CCCR2"},
  384.     {MSR_FLAME_CCCR3, "FLAME_CCCR3"},
  385.     {MSR_IQ_CCCR0, "IQ_CCCR0"},
  386.     {MSR_IQ_CCCR1, "IQ_CCCR1"},
  387.     {MSR_IQ_CCCR2, "IQ_CCCR2"},
  388.     {MSR_IQ_CCCR3, "IQ_CCCR3"},
  389.     {MSR_IQ_CCCR4, "IQ_CCCR4"},
  390.     {MSR_IQ_CCCR5, "IQ_CCCR5"},
  391.     {MSR_BSU_ESCR0, "BSU_ESCR0"},
  392.     {MSR_BSU_ESCR1, "BSU_ESCR1"},
  393.     {MSR_FSB_ESCR0, "FSB_ESCR0"},
  394.     {MSR_FSB_ESCR1, "FSB_ESCR1"},
  395.     {MSR_FIRM_ESCR0, "FIRM_ESCR0"},
  396.     {MSR_FIRM_ESCR1, "FIRM_ESCR1"},
  397.     {MSR_FLAME_ESCR0, "FLAME_ESCR0"},
  398.     {MSR_FLAME_ESCR1, "FLAME_ESCR1"},
  399.     {MSR_DAC_ESCR0, "DAC_ESCR0"},
  400.     {MSR_DAC_ESCR1, "DAC_ESCR1"},
  401.     {MSR_MOB_ESCR0, "MOB_ESCR0"},
  402.     {MSR_MOB_ESCR1, "MOB_ESCR1"},
  403.     {MSR_PMH_ESCR0, "PMH_ESCR0"},
  404.     {MSR_PMH_ESCR1, "PMH_ESCR1"},
  405.     {MSR_SAAT_ESCR0, "SAAT_ESCR0"},
  406.     {MSR_SAAT_ESCR1, "SAAT_ESCR1"},
  407.     {MSR_U2L_ESCR0, "U2L_ESCR0"},
  408.     {MSR_U2L_ESCR1, "U2L_ESCR1"},
  409.     {MSR_BPU_ESCR0, "BPU_ESCR0"},
  410.     {MSR_BPU_ESCR1, "BPU_ESCR1"},
  411.     {MSR_IS_ESCR0, "IS_ESCR0"},
  412.     {MSR_IS_ESCR1, "IS_ESCR1"},
  413.     {MSR_ITLB_ESCR0, "ITLB_ESCR0"},
  414.     {MSR_ITLB_ESCR1, "ITLB_ESCR1"},
  415.     {MSR_CRU_ESCR0, "CRU_ESCR0"},
  416.     {MSR_CRU_ESCR1, "CRU_ESCR1"},
  417.     {MSR_IQ_ESCR0, "IQ_ESCR0"},
  418.     {MSR_IQ_ESCR1, "IQ_ESCR1"},
  419.     {MSR_RAT_ESCR0, "RAT_ESCR0"},
  420.     {MSR_RAT_ESCR1, "RAT_ESCR1"},
  421.     {MSR_SSU_ESCR0, "SSU_ESCR0"},
  422.     {MSR_MS_ESCR0, "MS_ESCR0"},
  423.     {MSR_MS_ESCR1, "MS_ESCR1"},
  424.     {MSR_TBPU_ESCR0, "TBPU_ESCR0"},
  425.     {MSR_TBPU_ESCR1, "TBPU_ESCR1"},
  426.     {MSR_TC_ESCR0, "TC_ESCR0"},
  427.     {MSR_TC_ESCR1, "TC_ESCR1"},
  428.     {MSR_IX_ESCR0, "IX_ESCR0"},
  429.     {MSR_IX_ESCR1, "IX_ESCR1"},
  430.     {MSR_ALF_ESCR0, "ALF_ESCR0"},
  431.     {MSR_ALF_ESCR1, "ALF_ESCR1"},
  432.     {MSR_CRU_ESCR2, "CRU_ESCR2"},
  433.     {MSR_CRU_ESCR3, "CRU_ESCR3"},
  434.     {MSR_CRU_ESCR4, "CRU_ESCR4"},
  435.     {MSR_CRU_ESCR5, "CRU_ESCR5"},
  436.     {MSR_TC_PRECISE_EVENT, "TC_PRECISE_EVENT"},
  437.     {IA32_PEBS_ENABLE, "IA32_PEBS_ENABLE"},
  438.     {MSR_PEBS_MATRIX_VERT, "PEBS_MATRIX_VERT"},
  439.     /* use pentiumMcaEnable() or pentiumMcaShow()
  440.     {IA32_MC0_CTL, "IA32_MC0_CTL"},
  441.     {IA32_MC0_STATUS, "IA32_MC0_STATUS"},
  442.     {IA32_MC0_ADDR, "IA32_MC0_ADDR"},
  443.     {IA32_MC0_MISC, "IA32_MC0_MISC"},
  444.     {IA32_MC1_CTL, "IA32_MC1_CTL"},
  445.     {IA32_MC1_STATUS, "IA32_MC1_STATUS"},
  446.     {IA32_MC1_ADDR, "IA32_MC1_ADDR"},
  447.     {IA32_MC1_MISC, "IA32_MC1_MISC"},
  448.     {IA32_MC2_CTL, "IA32_MC2_CTL"},
  449.     {IA32_MC2_STATUS, "IA32_MC2_STATUS"},
  450.     {IA32_MC2_ADDR, "IA32_MC2_ADDR"},
  451.     {IA32_MC2_MISC, "IA32_MC2_MISC"},
  452.     {IA32_MC3_CTL, "IA32_MC3_CTL"},
  453.     {IA32_MC3_STATUS, "IA32_MC3_STATUS"},
  454.     {IA32_MC3_ADDR, "IA32_MC3_ADDR"},
  455.     {IA32_MC3_MISC, "IA32_MC3_MISC"},
  456.     */
  457.     {IA32_DS_AREA, "IA32_DS_AREA"},
  458.     };
  459. INT32 pentiumMsrP7NumEnt = NELEMENTS (pentiumMsrP7);
  460. /* locals */
  461. LOCAL char mtrrBusy = FALSE; /* MTRR busy flag */
  462. /*******************************************************************************
  463. *
  464. * pentiumMtrrEnable - enable MTRR (Memory Type Range Register)
  465. *
  466. * This routine enables the MTRR that provide a mechanism for associating the
  467. * memory types with physical address ranges in system memory.
  468. *
  469. * RETURNS: N/A
  470. */
  471. void pentiumMtrrEnable (void)
  472.     {
  473.     int oldLevel;
  474.     int deftype[2];
  475.     int oldCr4;
  476.     oldLevel = intLock ();                      /* LOCK INTERRUPT */
  477.     cacheFlush (DATA_CACHE, NULL, 0); /* flush cache w WBINVD */
  478.     oldCr4 = pentiumCr4Get (); /* save CR4 */
  479.     pentiumCr4Set (oldCr4 & ~CR4_PGE); /* clear PGE bit */
  480.     pentiumTlbFlush (); /* flush TLB */
  481.     pentiumMsrGet (MSR_MTRR_DEFTYPE, (LL_INT *)&deftype);
  482.     deftype[0] |= (MTRR_E | MTRR_FE); /* set enable bits */
  483.     pentiumMsrSet (MSR_MTRR_DEFTYPE, (LL_INT *)&deftype);
  484.     cacheFlush (DATA_CACHE, NULL, 0); /* flush cache w WBINVD */
  485.     pentiumTlbFlush (); /* flush TLB */
  486.     pentiumCr4Set (oldCr4); /* restore CR4 */
  487.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  488.     }
  489. /*******************************************************************************
  490. *
  491. * pentiumMtrrDisable - disable MTRR (Memory Type Range Register)
  492. *
  493. * This routine disables the MTRR that provide a mechanism for associating the
  494. * memory types with physical address ranges in system memory.
  495. *
  496. * RETURNS: N/A
  497. */
  498. void pentiumMtrrDisable (void)
  499.     {
  500.     int oldLevel;
  501.     int deftype[2];
  502.     int oldCr4;
  503.     oldLevel = intLock ();                      /* LOCK INTERRUPT */
  504.     cacheFlush (DATA_CACHE, NULL, 0); /* flush cache w WBINVD */
  505.     oldCr4 = pentiumCr4Get (); /* save CR4 */
  506.     pentiumCr4Set (oldCr4 & ~CR4_PGE); /* clear PGE bit */
  507.     pentiumTlbFlush (); /* flush TLB */
  508.     pentiumMsrGet (MSR_MTRR_DEFTYPE, (LL_INT *)&deftype);
  509.     deftype[0] &= ~(MTRR_E | MTRR_FE); /* clear enable bits */
  510.     pentiumMsrSet (MSR_MTRR_DEFTYPE, (LL_INT *)&deftype);
  511.     cacheFlush (DATA_CACHE, NULL, 0); /* flush cache w WBINVD */
  512.     pentiumTlbFlush (); /* flush TLB */
  513.     pentiumCr4Set (oldCr4); /* restore CR4 */
  514.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  515.     }
  516. /*******************************************************************************
  517. *
  518. * pentiumMtrrGet - get MTRRs to a specified MTRR table
  519. *
  520. * This routine gets MTRRs to a specified MTRR table with RDMSR instruction.
  521. * The read MTRRs are CAP register, DEFTYPE register, fixed range MTRRs, and
  522. * variable range MTRRs.
  523. *
  524. * RETURNS: OK, or ERROR if MTRR is being accessed.
  525. */
  526. STATUS pentiumMtrrGet
  527.     (
  528.     MTRR * pMtrr /* MTRR table */
  529.     )
  530.     {
  531.     int ix;
  532.     int addr = MSR_MTRR_PHYS_BASE0;
  533.     /* mutual exclusion ON */
  534.     if (pentiumBts (&mtrrBusy) != OK)
  535. return (ERROR);
  536.     pentiumMsrGet (MSR_MTRR_CAP, (LL_INT *)&pMtrr->cap);
  537.     pentiumMsrGet (MSR_MTRR_DEFTYPE, (LL_INT *)&pMtrr->deftype);
  538.     if (pMtrr->cap[0] & MTRR_FIX_SUPPORT)
  539. {
  540.         pentiumMsrGet (MSR_MTRR_FIX_00000, (LL_INT *)&pMtrr->fix[0].type);
  541.         pentiumMsrGet (MSR_MTRR_FIX_80000, (LL_INT *)&pMtrr->fix[1].type);
  542.         pentiumMsrGet (MSR_MTRR_FIX_A0000, (LL_INT *)&pMtrr->fix[2].type);
  543.         pentiumMsrGet (MSR_MTRR_FIX_C0000, (LL_INT *)&pMtrr->fix[3].type);
  544.         pentiumMsrGet (MSR_MTRR_FIX_C8000, (LL_INT *)&pMtrr->fix[4].type);
  545.         pentiumMsrGet (MSR_MTRR_FIX_D0000, (LL_INT *)&pMtrr->fix[5].type);
  546.         pentiumMsrGet (MSR_MTRR_FIX_D8000, (LL_INT *)&pMtrr->fix[6].type);
  547.         pentiumMsrGet (MSR_MTRR_FIX_E0000, (LL_INT *)&pMtrr->fix[7].type);
  548.         pentiumMsrGet (MSR_MTRR_FIX_E8000, (LL_INT *)&pMtrr->fix[8].type);
  549.         pentiumMsrGet (MSR_MTRR_FIX_F0000, (LL_INT *)&pMtrr->fix[9].type);
  550.         pentiumMsrGet (MSR_MTRR_FIX_F8000, (LL_INT *)&pMtrr->fix[10].type);
  551. }
  552.     for (ix = 0; ix < (pMtrr->cap[0] & MTRR_VCNT); ix++)
  553. {
  554.         pentiumMsrGet (addr++, &pMtrr->var[ix].base);
  555.         pentiumMsrGet (addr++, &pMtrr->var[ix].mask);
  556. }
  557.     /* mutual exclusion OFF */
  558.     (void) pentiumBtc (&mtrrBusy);
  559.     return (OK);
  560.     }
  561. /*******************************************************************************
  562. *
  563. * pentiumMtrrSet - set MTRRs from specified MTRR table with WRMSR instruction.
  564. *
  565. * This routine sets MTRRs from specified MTRR table with WRMSR instruction.
  566. * The written MTRRs are DEFTYPE register, fixed range MTRRs, and variable
  567. * range MTRRs.
  568. *
  569. * RETURNS: OK, or ERROR if MTRR is enabled or being accessed.
  570. */
  571. STATUS pentiumMtrrSet 
  572.     (
  573.     MTRR * pMtrr /* MTRR table */
  574.     )
  575.     {
  576.     int ix;
  577.     int addr = MSR_MTRR_PHYS_BASE0;
  578.     /* MTRR should be disabled */
  579.     pentiumMsrGet (MSR_MTRR_DEFTYPE, (LL_INT *)&pMtrr->deftype);
  580.     if ((pMtrr->deftype[0] & (MTRR_E | MTRR_FE)) != 0)
  581. return (ERROR);
  582.     /* mutual exclusion ON */
  583.     if (pentiumBts (&mtrrBusy) != OK)
  584. return (ERROR);
  585.     pentiumMsrSet (MSR_MTRR_DEFTYPE, (LL_INT *)&pMtrr->deftype);
  586.     pentiumMsrGet (MSR_MTRR_CAP, (LL_INT *)&pMtrr->cap);
  587.     if (pMtrr->cap[0] & MTRR_FIX_SUPPORT)
  588. {
  589.         pentiumMsrSet (MSR_MTRR_FIX_00000, (LL_INT *)&pMtrr->fix[0].type);
  590.         pentiumMsrSet (MSR_MTRR_FIX_80000, (LL_INT *)&pMtrr->fix[1].type);
  591.         pentiumMsrSet (MSR_MTRR_FIX_A0000, (LL_INT *)&pMtrr->fix[2].type);
  592.         pentiumMsrSet (MSR_MTRR_FIX_C0000, (LL_INT *)&pMtrr->fix[3].type);
  593.         pentiumMsrSet (MSR_MTRR_FIX_C8000, (LL_INT *)&pMtrr->fix[4].type);
  594.         pentiumMsrSet (MSR_MTRR_FIX_D0000, (LL_INT *)&pMtrr->fix[5].type);
  595.         pentiumMsrSet (MSR_MTRR_FIX_D8000, (LL_INT *)&pMtrr->fix[6].type);
  596.         pentiumMsrSet (MSR_MTRR_FIX_E0000, (LL_INT *)&pMtrr->fix[7].type);
  597.         pentiumMsrSet (MSR_MTRR_FIX_E8000, (LL_INT *)&pMtrr->fix[8].type);
  598.         pentiumMsrSet (MSR_MTRR_FIX_F0000, (LL_INT *)&pMtrr->fix[9].type);
  599.         pentiumMsrSet (MSR_MTRR_FIX_F8000, (LL_INT *)&pMtrr->fix[10].type);
  600. }
  601.     for (ix = 0; ix < (pMtrr->cap[0] & MTRR_VCNT); ix++)
  602. {
  603.         pentiumMsrSet (addr++, &pMtrr->var[ix].base);
  604.         pentiumMsrSet (addr++, &pMtrr->var[ix].mask);
  605. }
  606.     /* mutual exclusion OFF */
  607.     (void) pentiumBtc (&mtrrBusy);
  608.     return (OK);
  609.     }
  610. /*******************************************************************************
  611. *
  612. * pentiumPmcStart - start both PMC0 and PMC1
  613. *
  614. * SYNOPSIS
  615. * ss
  616. * STATUS pentiumPmcStart (pmcEvtSel0, pmcEvtSel1)
  617. *     int pmcEvtSel0; /@ Performance Event Select Register 0 @/
  618. *     int pmcEvtSel1; /@ Performance Event Select Register 1 @/
  619. * se
  620. * This routine starts both PMC0 (Performance Monitoring Counter 0) and PMC1
  621. * by writing specified events to Performance Event Select Registers. 
  622. * The first parameter is a content of Performance Event Select Register 0,
  623. * and the second parameter is for the Performance Event Select Register 1.
  624. *
  625. * RETURNS: OK or ERROR if PMC is already started.
  626. */
  627. STATUS   pentiumPmcStart
  628.     (
  629.     int pmcEvtSel0,
  630.     int pmcEvtSel1
  631.     )
  632.     {
  633.     STATUS retVal;
  634.     retVal = ERROR;
  635.     if (sysCpuId.featuresEdx & CPUID_MSR)
  636.         {
  637.         if (sysProcessor == X86CPU_PENTIUM)
  638.     {
  639.             if(pentiumP5PmcStart0(pmcEvtSel0) == OK    
  640.                     && pentiumP5PmcStart1(pmcEvtSel1) == OK) 
  641.                 retVal = OK;
  642.             }
  643.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  644.             retVal = pentiumP6PmcStart(pmcEvtSel0, pmcEvtSel1);
  645.         }
  646.     return (retVal);
  647.     }
  648.    
  649. /*******************************************************************************
  650. *
  651. * pentiumPmcStart0 - start PMC0
  652. *
  653. * SYNOPSIS
  654. * ss
  655. * STATUS pentiumPmcStart0 (pmcEvtSel0)
  656. *       int pmcEvtSel0;           /@ PMC0 control and event select @/
  657. * se
  658. *
  659. * This routine starts PMC0 (Performance Monitoring Counter 0) 
  660. * by writing specified PMC0 events to Performance Event Select Registers. 
  661. * The only parameter is the content of Performance Event Select Register.
  662. *
  663. * RETURNS: OK or ERROR if PMC is already started.
  664. */
  665. STATUS   pentiumPmcStart0
  666.     (
  667.     int pmcEvtSel0
  668.     )
  669.     {
  670.     if ((sysCpuId.featuresEdx & CPUID_MSR) && (sysProcessor == X86CPU_PENTIUM))
  671.        return (pentiumP5PmcStart0(pmcEvtSel0));            
  672.     else
  673.        return (ERROR);
  674.     }
  675. /*******************************************************************************
  676. *
  677. * pentiumPmcStart1 - start PMC1
  678. *
  679. * SYNOPSIS
  680. * ss
  681. * STATUS pentiumPmcStart1 (pmcEvtSel1)
  682. *       int pmcEvtSel1;           /@ PMC1 control and event select @/
  683. * se
  684. *
  685. * This routine starts PMC1 (Performance Monitoring Counter 0) 
  686. * by writing specified PMC1 events to Performance Event Select Registers. 
  687. * The only parameter is the content of Performance Event Select Register.
  688. *
  689. * RETURNS: OK or ERROR if PMC1 is already started.
  690. */
  691. STATUS   pentiumPmcStart1
  692.     (
  693.     int pmcEvtSel1
  694.     )
  695.     {
  696.     if ((sysCpuId.featuresEdx & CPUID_MSR) && (sysProcessor == X86CPU_PENTIUM))
  697.         return (pentiumP5PmcStart1(pmcEvtSel1));                
  698.     else
  699.         return (ERROR);
  700.     }
  701. /*******************************************************************************
  702. *
  703. * pentiumPmcStop - stop both PMC0 and PMC1
  704. *
  705. * SYNOPSIS
  706. * ss
  707. * void pentiumPmcStop (void)
  708. * se
  709. *
  710. * This routine stops both PMC0 (Performance Monitoring Counter 0)
  711. * and PMC1 by clearing two Performance Event Select Registers.
  712. *
  713. * RETURNS: N/A
  714. */
  715. void pentiumPmcStop (void)
  716.     {
  717.     if (sysCpuId.featuresEdx & CPUID_MSR)
  718. {
  719.         if (sysProcessor == X86CPU_PENTIUM)
  720.             {
  721.             pentiumP5PmcStop0();
  722.             pentiumP5PmcStop1();
  723.             }
  724.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  725.             pentiumP6PmcStop();
  726.         }
  727.     }
  728. /*******************************************************************************
  729. *
  730. * pentiumPmcStop0 - stop PMC0
  731. *
  732. * SYNOPSIS
  733. * ss
  734. * void pentiumPmcStop0 (void)
  735. * se
  736. *
  737. * This routine stops only PMC0 (Performance Monitoring Counter 0)
  738. * by clearing the PMC0 bits of Control and Event Select Register.
  739. *
  740. * RETURNS: N/A
  741. */
  742. void pentiumPmcStop0 (void)
  743.     {
  744.     if ((sysCpuId.featuresEdx & CPUID_MSR) && (sysProcessor == X86CPU_PENTIUM))
  745.         pentiumP5PmcStop0();
  746.     }
  747. /*******************************************************************************
  748. *
  749. * pentiumPmcStop1 - stop PMC1
  750. *
  751. * SYNOPSIS
  752. * ss
  753. * void pentiumPmcStop1 (void)
  754. * se
  755. *
  756. * This routine stops only PMC1 (Performance Monitoring Counter 1)
  757. * by clearing the PMC1 bits of Control and Event Select Register.
  758. *
  759. * RETURNS: N/A
  760. */
  761. void pentiumPmcStop1 (void)
  762.     {
  763.     if (sysCpuId.featuresEdx & CPUID_MSR)
  764.         {
  765.         if (sysProcessor == X86CPU_PENTIUM)
  766.             pentiumP5PmcStop1();
  767.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  768.             pentiumP6PmcStop1();
  769.         }
  770.     }
  771. /*******************************************************************************
  772. *
  773. * pentiumPmcGet - get the contents of PMC0 and PMC1
  774. *
  775. * SYNOPSIS
  776. * ss
  777. * void pentiumPmcGet (pPmc0, pPmc1)
  778. *     long long int * pPmc0;            /@ Performance Monitoring Counter 0 @/
  779. *     long long int * pPmc1;            /@ Performance Monitoring Counter 1 @/
  780. * se
  781. *
  782. * This routine gets the contents of both PMC0 (Performance Monitoring Counter 0)
  783. * and PMC1.  The first parameter is a pointer of 64Bit variable to store
  784. * the content of the Counter 0, and the second parameter is for the Counter 1.
  785. *
  786. * RETURNS: N/A
  787. */
  788. void pentiumPmcGet
  789.     (
  790.     long long int * pPmc0, 
  791.     long long int * pPmc1
  792.     )
  793.     {
  794.     if (sysCpuId.featuresEdx & CPUID_MSR)
  795.         {
  796.         if (sysProcessor == X86CPU_PENTIUM)
  797.             pentiumP5PmcGet(pPmc0, pPmc1);
  798.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  799.             pentiumP6PmcGet(pPmc0, pPmc1);
  800.         }
  801.     }
  802. /*******************************************************************************
  803. *
  804. * pentiumPmcGet0 - get the contents of PMC0
  805. *
  806. * SYNOPSIS
  807. * ss
  808. * void pentiumPmcGet0 (pPmc0)
  809. *     long long int * pPmc0;            /@ Performance Monitoring Counter 0 @/
  810. * se
  811. *
  812. * This routine gets the contents of PMC0 (Performance Monitoring Counter 0).
  813. * The parameter is a pointer of 64Bit variable to store the content of
  814. * the Counter.
  815. *
  816. * RETURNS: N/A
  817. */
  818. void pentiumPmcGet0
  819.     (
  820.     long long int * pPmc0
  821.     )
  822.     {
  823.     if (sysCpuId.featuresEdx & CPUID_MSR)
  824.         {
  825.         if (sysProcessor == X86CPU_PENTIUM)
  826.             pentiumP5PmcGet0(pPmc0);
  827.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  828.             pentiumP6PmcGet0(pPmc0);
  829.         }
  830.     }
  831. /*******************************************************************************
  832. *
  833. * pentiumPmcGet1 - get the contents of PMC1
  834. *
  835. * SYNOPSIS
  836. * ss
  837. * void pentiumPmcGet1 (pPmc1)
  838. *     long long int * pPmc1;            /@ Performance Monitoring Counter 1 @/
  839. * se
  840. *
  841. * This routine gets a content of PMC1 (Performance Monitoring Counter 1).
  842. * Parameter is a pointer of 64Bit variable to store the content of the Counter.
  843. *
  844. * RETURNS: N/A
  845. */
  846. void pentiumPmcGet1
  847.     (
  848.     long long int * pPmc1
  849.     )
  850.     {
  851.     if (sysCpuId.featuresEdx & CPUID_MSR)
  852.         {
  853.         if (sysProcessor == X86CPU_PENTIUM)
  854.             pentiumP5PmcGet1(pPmc1);
  855.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  856.             pentiumP6PmcGet1(pPmc1);
  857.         }
  858.     }
  859.     
  860. /*******************************************************************************
  861. *
  862. * pentiumPmcReset - reset both PMC0 and PMC1
  863. *
  864. * SYNOPSIS
  865. * ss
  866. * void pentiumPmcReset (void)
  867. * se
  868. * This routine resets both PMC0 (Performance Monitoring Counter 0) and PMC1.
  869. *
  870. * RETURNS: N/A
  871. */
  872. void pentiumPmcReset (void)
  873.     {
  874.     if (sysCpuId.featuresEdx & CPUID_MSR)
  875.         {
  876.         if (sysProcessor == X86CPU_PENTIUM)
  877.             pentiumP5PmcReset();
  878.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  879.             pentiumP6PmcReset();
  880.         }
  881.     }
  882. /*******************************************************************************
  883. *
  884. * pentiumPmcReset0 - reset PMC0
  885. *
  886. * SYNOPSIS
  887. * ss
  888. * void pentiumPmcReset0 (void)
  889. * se
  890. *
  891. * This routine resets PMC0 (Performance Monitoring Counter 0).
  892. *
  893. * RETURNS: N/A 
  894. */
  895. void pentiumPmcReset0 (void)
  896.     {
  897.     if (sysCpuId.featuresEdx & CPUID_MSR)
  898.         {
  899.         if (sysProcessor == X86CPU_PENTIUM)
  900.             pentiumP5PmcReset0();
  901.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  902.             pentiumP6PmcReset0();
  903.         }
  904.     }
  905. /*******************************************************************************
  906. *
  907. * pentiumPmcReset1 - reset PMC1
  908. *
  909. * SYNOPSIS
  910. * ss
  911. * void pentiumPmcReset1 (void)
  912. * se
  913. *
  914. * This routine resets PMC1 (Performance Monitoring Counter 1).
  915. *
  916. * RETURNS: N/A
  917. */
  918. void pentiumPmcReset1 (void)
  919.     {
  920.     if (sysCpuId.featuresEdx & CPUID_MSR)
  921.         {
  922.         if (sysProcessor == X86CPU_PENTIUM)
  923.             pentiumP5PmcReset1();
  924.         else if (sysProcessor == X86CPU_PENTIUMPRO)
  925.             pentiumP6PmcReset1();
  926.         }
  927.     }
  928. /*******************************************************************************
  929. *
  930. * pentiumMsrInit - initialize all the MSRs (Model Specific Register)
  931. *
  932. * This routine initializes all the MSRs in the processor.
  933. * This routine works on either P5, P6 or P7 family processors.
  934. *
  935. * RETURNS: OK, or ERROR if RDMSR/WRMSR instructions are not supported.
  936. */
  937. STATUS pentiumMsrInit (void)
  938.     {
  939.     PENTIUM_MSR * pMsr; /* pointer to the MSR table */
  940.     UINT32 value[2] = {0,0};
  941.     UINT32 zero[2]  = {0,0};
  942.     int ix;
  943.     /* just return if RDMSR and WRMSR instruction are not supported */
  944.     if ((sysCpuId.featuresEdx & CPUID_MSR) == 0)
  945. return (ERROR);
  946.     switch (sysProcessor)
  947. {
  948. case X86CPU_PENTIUM:
  949.     pMsr = pentiumMsrP5;
  950.          for (ix = 0; ix < pentiumMsrP5NumEnt; ix++, pMsr++)
  951.         {
  952.         switch (pMsr->addr)
  953.             {
  954.             case MSR_P5_MC_ADDR: /* disable the MCA */
  955.         pentiumMcaEnable (FALSE);
  956.                 break;
  957.             case MSR_CESR: /* disable the PM */
  958.                 pentiumMsrSet (pMsr->addr, (LL_INT *)&zero);
  959.                 break;
  960.             default:
  961.                 break;
  962.             }
  963.         }
  964.     break;
  965. case X86CPU_PENTIUMPRO: /* PENTIUM[23] */
  966.     pMsr = pentiumMsrP6;
  967.          for (ix = 0; ix < pentiumMsrP6NumEnt; ix++, pMsr++)
  968.         {
  969.         switch (pMsr->addr)
  970.             {
  971.             case MSR_APICBASE: /* don't touch */
  972.         /* bit-11 can't be re-enabled except by hard reset */
  973.                 break;
  974.             case MSR_ROB_CR_BKUPTMPDR6: /* set the default value */
  975.                 pentiumMsrGet (pMsr->addr, (LL_INT *)&value);
  976.            value[0] = MSR_ROB_CR_BKUPTMPDR6_DEFAULT;
  977.                 pentiumMsrSet (pMsr->addr, (LL_INT *)&value);
  978.                 break;
  979.             case MSR_MCG_CAP: /* disable the MCA */
  980.         pentiumMcaEnable (FALSE);
  981.                 break;
  982.             case MSR_DEBUGCTLMSR: /* disable the debug features */
  983.             case MSR_EVNTSEL0: /* disable the PM */
  984.             case MSR_EVNTSEL1: /* disable the PM */
  985.             case MSR_PERFCTR0: /* disable the PM */
  986.             case MSR_PERFCTR1: /* disable the PM */
  987.                 pentiumMsrSet (pMsr->addr, (LL_INT *)&zero);
  988.                 break;
  989.             default:
  990.                 break;
  991.             }
  992.         }
  993.     break;
  994. case X86CPU_PENTIUM4:
  995.     pMsr = pentiumMsrP7;
  996.          for (ix = 0; ix < pentiumMsrP7NumEnt; ix++, pMsr++)
  997.         {
  998.         switch (pMsr->addr)
  999.             {
  1000.             case IA32_APIC_BASE: /* don't touch */
  1001.         /* bit-11 can't be re-enabled except by hard reset */
  1002.                 break;
  1003.             case IA32_MISC_ENABLE: /* set the default value */
  1004.                 pentiumMsrGet (pMsr->addr, (LL_INT *)&value);
  1005.            value[0] = IA32_MISC_ENABLE_DEFAULT;
  1006.                 pentiumMsrSet (pMsr->addr, (LL_INT *)&value);
  1007.                 break;
  1008.             case IA32_MCG_CAP: /* disable the MCA */
  1009.         pentiumMcaEnable (FALSE);
  1010.                 break;
  1011.             case IA32_MISC_CTL: /* disable the serial number */
  1012.             case IA32_THERM_INTERRUPT: /* disable the thermal int. */
  1013.             case IA32_DEBUGCTL: /* disable the debug features */
  1014.             case MSR_TC_PRECISE_EVENT: /* disable the FE tagging */
  1015.             case IA32_PEBS_ENABLE: /* disable the PEBS */
  1016.             case MSR_BPU_CCCR0: /* disable the PM */
  1017.             case MSR_BPU_CCCR1: /* disable the PM */
  1018.             case MSR_BPU_CCCR2: /* disable the PM */
  1019.             case MSR_BPU_CCCR3: /* disable the PM */
  1020.             case MSR_MS_CCCR0: /* disable the PM */
  1021.             case MSR_MS_CCCR1: /* disable the PM */
  1022.             case MSR_MS_CCCR2: /* disable the PM */
  1023.             case MSR_MS_CCCR3: /* disable the PM */
  1024.             case MSR_FLAME_CCCR0: /* disable the PM */
  1025.             case MSR_FLAME_CCCR1: /* disable the PM */
  1026.             case MSR_FLAME_CCCR2: /* disable the PM */
  1027.             case MSR_FLAME_CCCR3: /* disable the PM */
  1028.             case MSR_IQ_CCCR0: /* disable the PM */
  1029.             case MSR_IQ_CCCR1: /* disable the PM */
  1030.             case MSR_IQ_CCCR2: /* disable the PM */
  1031.             case MSR_IQ_CCCR3: /* disable the PM */
  1032.             case MSR_IQ_CCCR4: /* disable the PM */
  1033.             case MSR_IQ_CCCR5: /* disable the PM */
  1034.                 pentiumMsrSet (pMsr->addr, (LL_INT *)&zero);
  1035.                 break;
  1036.             default:
  1037.                 break;
  1038.             }
  1039.         }
  1040.     break;
  1041. default:
  1042.     break;
  1043. }
  1044.     return (OK);
  1045.     }
  1046. /*******************************************************************************
  1047. *
  1048. * pentiumMcaEnable - enable/disable the MCA (Machine Check Architecture)
  1049. *
  1050. * This routine enables/disables 1) the Machine Check Architecture and its 
  1051. * Error Reporting register banks 2) the Machine Check Exception by toggling
  1052. * the MCE bit in the CR4.  This routine works on either P5, P6 or P7 family.
  1053. *
  1054. * RETURNS: N/A
  1055. */
  1056. void pentiumMcaEnable 
  1057.     (
  1058.     BOOL enable /* TRUE to enable, FALSE to disable the MCA */
  1059.     )
  1060.     {
  1061.     UINT32 zero[2] = {0x00000000,0x00000000};
  1062.     UINT32 one[2]  = {0xffffffff,0xffffffff};
  1063.     UINT32 cap[2]; /* MCG_CAP */
  1064.     int mcaBanks; /* MCA Error-Reporting Bank Registers */
  1065.     int ix;
  1066.     if ((sysCpuId.featuresEdx & CPUID_MCE) == CPUID_MCE)
  1067. {
  1068.         if ((sysCpuId.featuresEdx & CPUID_MCA) == CPUID_MCA)
  1069.     {
  1070.     pentiumMsrGet (MSR_MCG_CAP, (LL_INT *)&cap);
  1071.     /* enable/disable all the machine-check features */
  1072.     if (cap[0] & MCG_CTL_P)
  1073. {
  1074. if (enable)
  1075.     pentiumMsrSet (MSR_MCG_CTL, (LL_INT *)&one);
  1076. else
  1077.     pentiumMsrSet (MSR_MCG_CTL, (LL_INT *)&zero);
  1078. }
  1079.     mcaBanks = cap[0] & MCG_COUNT; /* get number of banks */
  1080.     /* enable all error-logging banks except MC0_CTL register */
  1081.     for (ix = 1; ix < mcaBanks; ix++)
  1082. pentiumMsrSet (MSR_MC0_CTL+(ix * 4), (LL_INT *)&one);
  1083.     /* clear all errors */
  1084.     for (ix = 0; ix < mcaBanks; ix++)
  1085. pentiumMsrSet (MSR_MC0_STATUS+(ix * 4), (LL_INT *)&zero);
  1086.     }
  1087. /* enable/disable the MCE exception */
  1088. if (enable)
  1089.     vxCr4Set (vxCr4Get () | CR4_MCE);
  1090. else
  1091.     vxCr4Set (vxCr4Get () & ~CR4_MCE);
  1092. }
  1093.     }