📄 pentiumalib.s
字号:
/* pentiumALib.s - Pentium and PentiumPro specific routines *//* Copyright 1984-1997 Wind River Systems, Inc. */ .data .globl _copyright_wind_river .long _copyright_wind_river/*modification history--------------------01d,24mar99,jdi doc: added basic formatting commands, absent despite thorough and long-standing coverage in WRS Coding Conventions.01b,17apr98,hdn fixed typo.01b,17apr98,hdn added documentation.01a,09jul97,hdn written.*//*DESCRIPTIONThis module contains Pentium and PentiumPro specific routines written in assembly language..SS "MCA (Machine Check Architecture)"The Pentium processor introduced a new exception called the machine-check exception (interrupt-18). This exception is used to signal hardware-relatederrors, such as a parity error on a read cycle. The PentiumPro processorextends the types of errors that can be detected and that generate a machine-check exception. It also provides a new machine-check architecture thatrecords information about a machine-check error and provides the basis for anextended error logging capability.MCA is enabled and its status registers are cleared zero in sysHwInit().Its registers are accessed by pentiumMsrSet() and pentiumMsrGet()..SS "PMC (Performance Monitoring Counters)"The PentiumPro processor has two performance-monitoring counters for use inmonitoring internal hardware operations. These counters are duration or eventcounters that can be programmed to count any of approximately 100 differenttypes of events, such as the number of instructions decoded, number of interrupts received, or number of cache loads.There are nine routines to interface the PMC. These nine routines are:.CS STATUS pentiumPmcStart ( int pmcEvtSel0; /@ performance event select register 0 @/ int pmcEvtSel1; /@ performance event select register 1 @/ ) void pentiumPmcStop (void) void pentiumPmcStop1 (void) void pentiumPmcGet ( long long int * pPmc0; /@ performance monitoring counter 0 @/ long long int * pPmc1; /@ performance monitoring counter 1 @/ ) void pentiumPmcGet0 ( long long int * pPmc0; /@ performance monitoring counter 0 @/ ) void pentiumPmcGet1 ( long long int * pPmc1; /@ performance monitoring counter 1 @/ ) void pentiumPmcReset (void) void pentiumPmcReset0 (void) void pentiumPmcReset1 (void).CEpentiumPmcStart() starts both PMC0 and PMC1. pentiumPmcStop() stops them, and pentiumPmcStop1() stops only PMC1. pentiumPmcGet() gets contents of PMC0 and PMC1. pentiumPmcGet0() getscontents of PMC0, and pentiumPmcGet1() gets contents of PMC1.pentiumPmcReset() resets both PMC0 and PMC1. pentiumPmcReset0() resetsPMC0, and pentiumPmcReset1() resets PMC1.PMC is enabled in sysHwInit(). Selected events in the default configurationare PMC0 = number of hardware interrupts received and PMC1 = number of misaligned data memory references..SS "MSR (Model Specific Register)"The concept of model-specific registers (MSRs) to control hardware functionsin the processor or to monitor processor activity was introduced in the PentiumPro processor. The new registers control the debug extensions, the performance counters, the machine-check exception capability, the machinecheck architecture, and the MTRRs. The MSRs can be read and written to usingthe RDMSR and WRMSR instructions, respectively.There are two routines to interface the MSR. These two routines are:.CS void pentiumMsrGet ( int address, /@ MSR address @/ long long int * pData /@ MSR data @/ ) void pentiumMsrSet ( int address, /@ MSR address @/ long long int * pData /@ MSR data @/ ).CEpentiumMsrGet() get contents of the specified MSR, and pentiumMsrSet() sets value to the specified MSR..SS "TSC (Time Stamp Counter)"The PentiumPro processor provides a 64-bit time-stamp counter that is incremented every processor clock cycle. The counter is incremented evenwhen the processor is halted by the HLT instruction or the external STPCLK#pin. The time-stamp counter is set to 0 following a hardware reset of theprocessor. The RDTSC instruction reads the time stamp counter and is guaranteed to return a monotonically increasing unique value whenever executed, except for 64-bit counter wraparound. Intel guarantees, architecturally, that the time-stamp counter frequency and configuration willbe such that it will not wraparound within 10 years after being reset to 0.The period for counter wrap is several thousands of years in the PentiumProand Pentium processors.There are three routines to interface the TSC. These three routines are:.CS void pentiumTscReset (void) void pentiumTscGet32 (void) void pentiumTscGet64 ( long long int * pTsc /@ TSC @/ ).CEpentiumTscReset() resets the TSC. pentiumTscGet32() gets the lower half of the64Bit TSC, and pentiumTscGet64() gets the entire 64Bit TSC.Four other routines are provided in this library. They are:.CS void pentiumTlbFlush (void) void pentiumSerialize (void) STATUS pentiumBts ( char * pFlag /@ flag address @/ ) STATUS pentiumBtc (pFlag) ( char * pFlag /@ flag address @/ ).CEpentiumTlbFlush() flushes TLBs (Translation Lookaside Buffers). pentiumSerialize() does serialization by executing CPUID instruction.pentiumBts() executes an atomic compare-and-exchange instruction to set a bit.pentiumBtc() executes an atomic compare-and-exchange instruction to clear a bit.INTERNALMany routines in this module doesn't use the "c" frame pointer %ebp@ !This is only for the benefit of the stacktrace facility to allow it to properly trace tasks executing within these routines.SEE ALSO: .I "Pentium, PentiumPro Family Developer's Manual"*/#define _ASMLANGUAGE#include "vxWorks.h"#include "asm.h"#include "regs.h"#include "arch/i86/pentiumLib.h" /* globals */ .globl _pentiumCr4Get .globl _pentiumCr4Set .globl _pentiumPmcStart .globl _pentiumPmcStop .globl _pentiumPmcStop1 .globl _pentiumPmcGet .globl _pentiumPmcGet0 .globl _pentiumPmcGet1 .globl _pentiumPmcReset .globl _pentiumPmcReset0 .globl _pentiumPmcReset1 .globl _pentiumTscGet64 .globl _pentiumTscGet32 .globl _pentiumTscReset .globl _pentiumMsrGet .globl _pentiumMsrSet .globl _pentiumTlbFlush .globl _pentiumSerialize .globl _pentiumBts .globl _pentiumBtc .data .align 4,0x90_pmcBusy: .byte 0x00 /* PMC busy flag, 1 = busy *//********************************************************************************* pentiumCr4Get - get contents of CR4 register** This routine gets the contents of the CR4 register.** RETURNS: Contents of CR4 register.* int pentiumCr4Get (void) */ .text .align 4,0x90_pentiumCr4Get: movl %cr4,%eax ret/********************************************************************************* pentiumCr4Set - sets specified value to the CR4 register** This routine sets a specified value to the CR4 register.** RETURNS: N/A* void pentiumCr4Set (cr4)* int cr4; /@ value to write CR4 register @/ */ .align 4,0x90_pentiumCr4Set: movl 4(%esp),%eax movl %eax,%cr4 ret/********************************************************************************* pentiumPmcStart - start both PMC0 and PMC1** This routine starts both PMC0 (Performance Monitoring Counter 0) and PMC1* by writing specified events to Performance Event Select Registers. * The first parameter is a content of Performance Event Select Register 0,* and the second parameter is for the Performance Event Select Register 1.** RETURNS: OK or ERROR if PMC is already started.* STATUS pentiumPmcStart (pmcEvtSel0, pmcEvtSel1)* int pmcEvtSel0; /@ Performance Event Select Register 0 @/* int pmcEvtSel1; /@ Performance Event Select Register 1 @/ */ .align 4,0x90_pentiumPmcStart: xorl %eax,%eax movl $ TRUE, %edx lock /* lock the BUS */ cmpxchgb %edx,_pmcBusy /* if (_pmcBusy == 0) */ jnz pentiumPmcStart0 /* {ZF = 1; _pmcBusy = TRUE;} */ movl SP_ARG1(%esp),%eax /* low-order 32 bits */ xorl %edx,%edx /* high-order 32 bits */ movl $ MSR_EVNTSEL0,%ecx /* specify MSR_EVNTSEL0 */ wrmsr /* write %edx:%eax to MSR_EVNTSEL0 */ movl SP_ARG2(%esp),%eax /* low-order 32 bits */ xorl %edx,%edx /* high-order 32 bits */ movl $ MSR_EVNTSEL1,%ecx /* specify MSR_EVNTSEL1 */ wrmsr /* write %edx:%eax to MSR_EVNTSEL1 */ xorl %eax,%eax /* return OK */ retpentiumPmcStart0: movl $ ERROR,%eax ret/********************************************************************************* pentiumPmcStop - stop both PMC0 and PMC1** This routine stops both PMC0 (Performance Monitoring Counter 0) and PMC1* by clearing two Performance Event Select Registers.** RETURNS: N/A* void pentiumPmcStop (void) */ .align 4,0x90_pentiumPmcStop: xorl %eax,%eax /* zero low-order 32 bits */ xorl %edx,%edx /* zero high-order 32 bits */ movl $ MSR_EVNTSEL0,%ecx /* specify MSR_EVNTSEL0 */ wrmsr /* write %edx:%eax to MSR_EVNTSEL0 */ movl $ MSR_EVNTSEL1,%ecx /* specify MSR_EVNTSEL1 */ wrmsr /* write %edx:%eax to MSR_EVNTSEL1 */ movl $ TRUE, %eax xorl %edx,%edx lock /* lock the BUS */ cmpxchgb %edx,_pmcBusy /* if (_pmcBusy == TRUE) */ ret /* {ZF = 1; _pmcBusy = 0;} *//********************************************************************************* pentiumPmcStop1 - stop PMC1** This routine stops only PMC1 (Performance Monitoring Counter 1)* by clearing the Performance Event Select Register 1.* Note, clearing the Performance Event Select Register 0 stops both counters,* PMC0 and PMC1.** RETURNS: N/A* void pentiumPmcStop1 (void) */ .align 4,0x90_pentiumPmcStop1: xorl %eax,%eax /* zero low-order 32 bits */ xorl %edx,%edx /* zero high-order 32 bits */ movl $ MSR_EVNTSEL1,%ecx /* specify MSR_EVNTSEL1 */ wrmsr /* write %edx:%eax to MSR_EVNTSEL1 */ ret/********************************************************************************* pentiumPmcGet - get the contents of PMC0 and PMC1** This routine gets the contents of both PMC0 (Performance Monitoring Counter 0)* and PMC1. The first parameter is a pointer of 64Bit variable to store* the content of the Counter 0, and the second parameter is for the Counter 1.** RETURNS: N/A* void pentiumPmcGet (pPmc0, pPmc1)* long long int * pPmc0; /@ Performance Monitoring Counter 0 @/* long long int * pPmc1; /@ Performance Monitoring Counter 1 @/ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -