Performance-Monitoring 是Intel提供的可以監測統計CPU內部所產生事件的一組方法。在Intel的手冊上介紹了兩類CPU事件監測方法:architectural performance monitoring 和 non-architectural performance monitoring。Architectural performance monitoring與平臺(CPU系列)無關但所能監測的事件少;non-architectural performance monitoring與平臺密切相關,能監測大量事件。我僅關注architectural performance monitoring。
Architectural performance monitoring介紹
CPU 通過兩個寄存器來完成事件監測工作:事件選擇寄存器IA32_PERFEVTSELx ( programming performance event select registers)和計數器IA32_PMCx (performance monitoring counter)。在計數前,設置事件選擇寄存器并將計數器清零;計數結束時,讀取計數器。
IA32_PERFEVTSELx與 IA32_PMCx都是成對使用,共同完成計數工作。IA32_PMCx寄存器對應于從0xc1開始的一段連續地址,IA32_PERFEVTSELx寄 存器對應于從0x186開始的一段連續地址。每種CPU的寄存器位數和可以使用的寄存器對數可能不一樣,但可以通過CUPID.0AH:EAX指令來獲取 這些元信息:
Bits 07 - 00: Version ID of architectural performance monitoring, If >0, architectural performance monitoring capability is supported.
Bits 15- 08: Number of general-purpose performance monitoring counter per logical processor
Bits 23 - 16: Bit width of general-purpose, performance monitoring counter
Bits 31 - 24: Length of EBX bit vector to enumerate architectural performance monitoring events
事件選擇寄存器IA32_PERFEVTSELx的配置
?
Event select field (bits 0 through 7):事件選擇碼區填寫需要監測的事件碼,這些事件碼都是事先定義好的,可以在Intel的手冊中查找。
Unit mask (UMASK) field (bits 8 through 15):掩碼區填寫與事件選擇碼對應掩碼,掩碼與事件碼共同使用來確定要監測的事件,掩碼與事件碼一樣是事先定義好的,可在Intel手冊上查找。
USR (user mode) flag (bit 16):標識是否統計CPU處于用戶態(CPU處于特權級別為:1、2、3)下發生的事件。可以與下面的OS位配合使用。
OS (operating system mode) flag (bit 17):標識是否統計CPU處于系統態(CPU處于特權級別為0)下發生的事件。可以與上面的USR位配合使用。
EN (Enable Counters) Flag (bit 22):計數允許位。注意:在寫計數器IA32_PMCx之前,必須清除計數允許位(設為0)。
Counter mask (CMASK) field (bits 24 through 31):計算器掩碼,如它不為零,但事件發生是,只有它小于計數器的值,計數器計數才會增加1。
計數示例
下面代碼是統計事件DTLB_MISSES.ANY,其事件碼為0x08,掩碼為0x01。
//寄存器地址碼
#define IA32_PMC0 0xc1
#define IA32_PERFEVTSEL0 0x186
//事件碼及其掩碼
#define EVENT 0x08
#define MASK 0x01
Int nEventMask, nCount;
Int nEventRegisterHigh,nEventRegisterLow;
Architectural performance monitoring介紹
CPU 通過兩個寄存器來完成事件監測工作:事件選擇寄存器IA32_PERFEVTSELx ( programming performance event select registers)和計數器IA32_PMCx (performance monitoring counter)。在計數前,設置事件選擇寄存器并將計數器清零;計數結束時,讀取計數器。
IA32_PERFEVTSELx與 IA32_PMCx都是成對使用,共同完成計數工作。IA32_PMCx寄存器對應于從0xc1開始的一段連續地址,IA32_PERFEVTSELx寄 存器對應于從0x186開始的一段連續地址。每種CPU的寄存器位數和可以使用的寄存器對數可能不一樣,但可以通過CUPID.0AH:EAX指令來獲取 這些元信息:
Bits 07 - 00: Version ID of architectural performance monitoring, If >0, architectural performance monitoring capability is supported.
Bits 15- 08: Number of general-purpose performance monitoring counter per logical processor
Bits 23 - 16: Bit width of general-purpose, performance monitoring counter
Bits 31 - 24: Length of EBX bit vector to enumerate architectural performance monitoring events
事件選擇寄存器IA32_PERFEVTSELx的配置
?

Event select field (bits 0 through 7):事件選擇碼區填寫需要監測的事件碼,這些事件碼都是事先定義好的,可以在Intel的手冊中查找。
Unit mask (UMASK) field (bits 8 through 15):掩碼區填寫與事件選擇碼對應掩碼,掩碼與事件碼共同使用來確定要監測的事件,掩碼與事件碼一樣是事先定義好的,可在Intel手冊上查找。
USR (user mode) flag (bit 16):標識是否統計CPU處于用戶態(CPU處于特權級別為:1、2、3)下發生的事件。可以與下面的OS位配合使用。
OS (operating system mode) flag (bit 17):標識是否統計CPU處于系統態(CPU處于特權級別為0)下發生的事件。可以與上面的USR位配合使用。
EN (Enable Counters) Flag (bit 22):計數允許位。注意:在寫計數器IA32_PMCx之前,必須清除計數允許位(設為0)。
Counter mask (CMASK) field (bits 24 through 31):計算器掩碼,如它不為零,但事件發生是,只有它小于計數器的值,計數器計數才會增加1。
計數示例
下面代碼是統計事件DTLB_MISSES.ANY,其事件碼為0x08,掩碼為0x01。
//寄存器地址碼
#define IA32_PMC0 0xc1
#define IA32_PERFEVTSEL0 0x186
//事件碼及其掩碼
#define EVENT 0x08
#define MASK 0x01
Int nEventMask, nCount;
Int nEventRegisterHigh,nEventRegisterLow;
nEventMask = IA32_PERFEVTSEL0;
nCount = IA32_PMC0;
nEventRegisterHigh=nEventRegisterLow=0;
//設置事件碼及掩碼
nEventRegisterLow |= EVENT;
nEventRegisterLow |= MASK<<8;
//設置用戶態系統態標識位
nEventRegisterLow |= 1<<16;
nEventRegisterLow |= 1<<17;
//清楚計數允許位
nEventRegisterLow &= ~(1<<22);
//設置事件選擇寄存器
wrmsr(nEventMask, -(u32)( nEventRegisterLowl), -1);
//計數器清零
wrmsr(nCount, -(u32)( 0), -1);
//設置計數允許位
nEventRegisterLow |= 1<<22;
wrmsr(nEventMask, -(u32)( nEventRegisterLowl), -1);
nCount = IA32_PMC0;
nEventRegisterHigh=nEventRegisterLow=0;
//設置事件碼及掩碼
nEventRegisterLow |= EVENT;
nEventRegisterLow |= MASK<<8;
//設置用戶態系統態標識位
nEventRegisterLow |= 1<<16;
nEventRegisterLow |= 1<<17;
//清楚計數允許位
nEventRegisterLow &= ~(1<<22);
//設置事件選擇寄存器
wrmsr(nEventMask, -(u32)( nEventRegisterLowl), -1);
//計數器清零
wrmsr(nCount, -(u32)( 0), -1);
//設置計數允許位
nEventRegisterLow |= 1<<22;
wrmsr(nEventMask, -(u32)( nEventRegisterLowl), -1);
。。。。//計數中
//讀起計數結果
rdmsr(nCount, nEventRegisterLow, nEventRegisterHigh);
rdmsr(nCount, nEventRegisterLow, nEventRegisterHigh);
Non-architectural performance monitoring介紹
(還不太了解這方面的知識!)
(還不太了解這方面的知識!)
?
http://rf-lai.spaces.live.com/blog/cns!8A6F01FE4875D04A!412.entry