詳解:基于 perf_events 的用戶態(tài)性能監(jiān)控中斷機(jī)制)
Linux PowerPC PMU 事件分支EBB詳解基于 perf_events 的用戶態(tài)性能監(jiān)控中斷機(jī)制【免費(fèi)下載鏈接】linuxLinux kernel source tree項(xiàng)目地址: https://gitcode.com/GitHub_Trending/li/linux導(dǎo)讀Event Based BranchesEBB事件分支是 Power 處理器提供的一項(xiàng)硬件特性當(dāng)指定事件如 PMU 計(jì)數(shù)器溢出發(fā)生時(shí)硬件直接跳轉(zhuǎn)到用戶空間預(yù)先指定的地址執(zhí)行處理代碼全程無(wú)需陷入內(nèi)核。本文以 Linux 內(nèi)核源碼樹中 Documentation/arch/powerpc/pmu-ebb.rst 為主線結(jié)合 arch/powerpc/perf/core-book3s.c 的 EBB 實(shí)現(xiàn)與 tools/testing/selftests/powerpc/pmu/ebb/ 測(cè)試套件系統(tǒng)講解如何通過(guò) Linuxperf_eventsAPI 配置 Power PMU 生成 EBB包括事件創(chuàng)建約束、啟用判定、處理器編寫規(guī)范以及 fork 語(yǔ)義并深入剖析內(nèi)核層的調(diào)度與上下文切換實(shí)現(xiàn)。什么是 EBB硬件直接分支到用戶態(tài)地址EBBEvent Based Branches允許硬件在特定事件發(fā)生時(shí)直接分支到用戶空間指定的地址執(zhí)行代碼全程無(wú)需陷入內(nèi)核。文檔明確說(shuō)明其完整規(guī)范定義于 Power ISA v2.07。當(dāng)前倉(cāng)庫(kù)的 arch/powerpc/include/asm/reg.h 中定義了三組與 EBB 直接相關(guān)的特殊寄存器#define SPRN_EBBHR 804 /* Event based branch handler register */ #define SPRN_EBBRR 805 /* Event based branch return register */ #define SPRN_BESCR 806 /* Branch event status and control register */ #define BESCR_GE 0x8000000000000000ULL /* Global Enable */EBBHREBB 處理程序的入口地址Handler Register由用戶態(tài)通過(guò)mtspr(SPRN_EBBHR, entry)寫入。EBBRREBB 返回地址寄存器Return Register事件發(fā)生后硬件會(huì)把被打斷的指令地址保存在這里處理程序用rfebb指令返回。BESCR分支事件狀態(tài)與控制寄存器Branch Event Status and Control Register其 bit 0 為全局使能位BESCR_GEGlobal Enable。此外還有BESCR_PMEPMU EBB 使能與BESCR_PMEOPMU EBB 溢出狀態(tài)等位詳見 selftests 中的使用。需要 EBB 配置的事件類型之一是PMU 異常當(dāng)性能計(jì)數(shù)器溢出時(shí)硬件不是進(jìn)入內(nèi)核中斷處理而是把控制權(quán)直接交給用戶態(tài)注冊(cè)的 EBB 處理程序。這正是本文主題——通過(guò) Linuxperf_eventsAPI 為 Power PMU 配置 EBB。術(shù)語(yǔ)約定EBB 事件文檔約定全文所稱的 EBB eventEBB 事件指的就是一個(gè)在attr.config中設(shè)置了 EBB 標(biāo)志的struct perf_event。硬件 PMU 上所有可配置的事件類型都可以作為 EBB 事件。內(nèi)核側(cè)對(duì)該標(biāo)志的判定位于 arch/powerpc/perf/core-book3s.c 的is_ebb_event()static bool is_ebb_event(struct perf_event *event) { /* * This could be a per-PMU callback, but wed rather avoid the cost. We * check that the PMU supports EBB, meaning those that dont can still * use bit 63 of the event code for something else if they wish. */ return (ppmu-flags PPMU_ARCH_207S) ((event-attr.config PERF_EVENT_CONFIG_EBB_SHIFT) 1); }判定有兩個(gè)前提其一是當(dāng)前 PMU 必須具備 Power ISA 2.07ARCH 207S能力標(biāo)志其二是事件編碼的 bit 63 被置位。UAPI 頭文件 arch/powerpc/include/uapi/asm/perf_event.h 給出了該位的確切定義/* * We use bit 63 of perf_event_attr.config as a flag to request EBB. */ #define PERF_EVENT_CONFIG_EBB_SHIFT 63值得注意的是內(nèi)核特意把PMU 是否支持 EBB與bit 63 的語(yǔ)義分開處理不支持 EBB 的 PMU 仍可自由使用 bit 63 編碼其它含義互不沖突。設(shè)計(jì)約束EBB 只適合自我監(jiān)控文檔在 Background 一節(jié)闡述了 EBB 的幾個(gè)根本性設(shè)計(jì)約束EBB 投遞給當(dāng)前運(yùn)行進(jìn)程當(dāng) PMU EBB 發(fā)生時(shí)它被投遞給當(dāng)前正在運(yùn)行的進(jìn)程因此 EBB 只能被程序用于自我監(jiān)控self-monitoring。跨進(jìn)程附加事件是可能的perf_events特性允許在標(biāo)準(zhǔn)權(quán)限檢查下為其它進(jìn)程創(chuàng)建事件EBB 事件也不例外。但是如果目標(biāo)進(jìn)程自己沒有通過(guò)mtspr(BESCR)啟用 EBBEBB 永遠(yuǎn)不會(huì)被投遞。因此理論上可以出現(xiàn)這樣的場(chǎng)景進(jìn)程 A 為自己?jiǎn)⒂?EBB 但不配置任何事件之后進(jìn)程 B 把 EBB 事件附加到進(jìn)程 A 上從而向 A 投遞 EBB。文檔坦言尚不清楚這種做法是否真的有用Its not clear if this is actually useful這屬于 API 能力的自然延伸而非推薦用法。PMU 全局獨(dú)占一旦 PMU 被配置為 EBB 模式所有 PMU 中斷都投遞給用戶進(jìn)程。這意味著只要有一個(gè) EBB 事件被調(diào)度到 PMU 上就不能再配置任何非 EBB 事件——EBB 事件無(wú)法與常規(guī)perf命令或任何其它 perf 事件并發(fā)運(yùn)行。反過(guò)來(lái)在使用了 EBB 的進(jìn)程上運(yùn)行perf命令是安全的內(nèi)核一般會(huì)正常調(diào)度 EBB 事件而perf會(huì)收到它的事件無(wú)法運(yùn)行的通知。獨(dú)占與優(yōu)先級(jí)pinned exclusive 的互斥實(shí)現(xiàn)EBB 事件與常規(guī)事件之間的互斥是通過(guò)perf_events既有的pinned釘住與exclusive獨(dú)占屬性實(shí)現(xiàn)的EBB 事件優(yōu)先于其它事件被調(diào)度除非對(duì)方也是 pinned 事件若一個(gè) EBB 事件與一個(gè)常規(guī)事件都是 pinned則先啟用的那個(gè)被調(diào)度成功另一個(gè)進(jìn)入錯(cuò)誤狀態(tài)error state。這層語(yǔ)義在內(nèi)核端由ebb_event_check()arch/powerpc/perf/core-book3s.c強(qiáng)制校驗(yàn)并在啟用 EBB 事件一節(jié)進(jìn)一步說(shuō)明其可觀測(cè)行為。創(chuàng)建 EBB 事件嚴(yán)格的屬性約束要請(qǐng)求一個(gè)事件按 EBB 方式計(jì)數(shù)需滿足文檔列出的以下規(guī)則1. 事件編碼 bit 63 置位e-attr.config | (1ull 63);這正是 selftests 中 ebb.c 的event_ebb_init()的實(shí)現(xiàn)與 UAPI 的PERF_EVENT_CONFIG_EBB_SHIFT完全對(duì)應(yīng)。2. 必須設(shè)置 pinned 與 exclusiveEBB 事件必須以 pinned 和 exclusive 屬性創(chuàng)建。若創(chuàng)建的是事件組只有組領(lǐng)導(dǎo)者leader可以設(shè)置這兩個(gè)屬性。selftests 中 ebb.c 的event_leader_ebb_init()展示了完整初始化方式void event_leader_ebb_init(struct event *e) { event_ebb_init(e); e-attr.exclusive 1; e-attr.pinned 1; }3. 禁止設(shè)置的屬性EBB 事件不得設(shè)置以下任一屬性禁止屬性含義原因inherit子進(jìn)程繼承事件EBB 不跨 fork 繼承見后文且會(huì)破壞任務(wù)綁定語(yǔ)義sample_period采樣周期EBB 由硬件直接投遞無(wú)需內(nèi)核采樣freq頻率模式同上內(nèi)核無(wú)法介入頻率計(jì)算enable_on_execexec 時(shí)自動(dòng)啟用EBB 使能必須由用戶態(tài)顯式控制內(nèi)核在ebb_event_check()中逐項(xiàng)校驗(yàn)這些規(guī)則static int ebb_event_check(struct perf_event *event) { struct perf_event *leader event-group_leader; /* Event and group leader must agree on EBB */ if (is_ebb_event(leader) ! is_ebb_event(event)) return -EINVAL; if (is_ebb_event(event)) { if (!(event-attach_state PERF_ATTACH_TASK)) return -EINVAL; if (!leader-attr.pinned || !leader-attr.exclusive) return -EINVAL; if (event-attr.freq || event-attr.inherit || event-attr.sample_type || event-attr.sample_period || event-attr.enable_on_exec) return -EINVAL; } return 0; }可見校驗(yàn)共四條組內(nèi) EBB 一致性、必須掛到任務(wù)PERF_ATTACH_TASK、組長(zhǎng)必須 pinnedexclusive、禁止上述屬性。任何一條不滿足都返回-EINVAL。event_attributes_test.c測(cè)試程序即圍繞這些約束展開正反用例驗(yàn)證見 event_attributes_test.c。4. 必須附加到任務(wù)EBB 事件必須附加到一個(gè)任務(wù)上通過(guò)向perf_event_open()傳入pid值指定通常傳0表示當(dāng)前任務(wù)。這與PERF_ATTACH_TASK的校驗(yàn)一致——沒有任務(wù)上下文EBB 無(wú)處投遞。5. 組內(nèi)事件必須統(tǒng)一事件組內(nèi)所有成員必須就 EBB 達(dá)成一致要么全部請(qǐng)求 EBB要么全部不請(qǐng)求。內(nèi)核在ebb_event_check()中通過(guò)比較is_ebb_event(leader)與is_ebb_event(event)強(qiáng)制這一點(diǎn)。值得補(bǔ)充的是從該函數(shù)可見非領(lǐng)導(dǎo)成員可以有自己的config但組的 pinned/exclusive 屬性只看 leader因此一個(gè)事件組中只有 leader 的 config bit 63 決定組屬性是否合法。6. 必須指定 PMCEBB 事件必須指明要計(jì)數(shù)所在的 PMCPerformance Monitor Counter這樣用戶態(tài)才能可靠地判斷事件被調(diào)度到哪一個(gè) PMC 上從而在 EBB 處理程序中讀取正確的SPRN_PMCn寄存器。selftests 通過(guò)ebb_enable_pmc_counting(pmc)記錄到ebb_state.pmc_enable[]與write_pmc()/read_pmc()ebb.c體現(xiàn)這一約定。啟用 EBB 事件ioctl / prctl 與 read() 判定事件成功 open 之后需要啟用它。文檔給出兩種途徑ioctl() 接口對(duì)事件 fd 調(diào)用PERF_EVENT_IOC_ENABLEprctl() 接口通過(guò)PR_TASK_PERF_EVENTS_ENABLE啟用任務(wù)的全部事件。selftests 中 ebb.c 的event_enable()走 ioctl 路徑而其調(diào)用序列展示了完整的啟用流程FAIL_IF(event_open(event)); ebb_enable_pmc_counting(1); setup_ebb_handler(standard_ebb_callee); ebb_global_enable(); FAIL_IF(event_enable(event)); if (event_read(event)) { /* ... EBB 未能調(diào)度通知父進(jìn)程錯(cuò)誤 ... */ return 2; }這里的關(guān)鍵是文檔強(qiáng)調(diào)的語(yǔ)義由于perf_eventsAPI 的設(shè)計(jì)啟用事件并不保證它已被調(diào)度到 PMU 上。要確認(rèn) EBB 事件確實(shí)被調(diào)度必須對(duì)事件執(zhí)行一次read()。若read()返回 EOF說(shuō)明事件沒有被調(diào)度EBB 并未啟用。event_read()正是包裝了對(duì)事件 fd 的read()調(diào)用。這一行為的根源是 EBB 事件同時(shí)具備 pinned 與 exclusive 屬性EBB 事件被啟用時(shí)會(huì)強(qiáng)制把所有非 pinned 事件趕下 PMU此時(shí)啟用成功但如果 PMU 上已經(jīng)有一個(gè) pinned 事件那么本次啟用不成功——于是read()返回 EOF調(diào)用方據(jù)此得知 EBB 未生效。一個(gè)完整的 EBB 使能序列來(lái)自 selftestsebb.c 的ebb_global_enable()與setup_ebb_handler()展示了用戶在事件創(chuàng)建/啟用之外必須完成的硬件準(zhǔn)備工作void ebb_global_enable(void) { /* Enable EBBs globally and PMU EBBs */ mtspr(SPRN_BESCR, 0x8000000100000000ull); mb(); }寫入BESCR的值0x8000000100000000含義清晰最高位即BESCR_GE全局使能bit 32 即 PMU EBB 使能位BESCR_PME。同時(shí)用戶態(tài)還必須先寫好 EBBHRvoid setup_ebb_handler(void (*callee)(void)) { ... /* Ensure ebb_user_func is set before we set the handler */ mb(); mtspr(SPRN_EBBHR, entry); /* Make sure the handler is set before we return */ mb(); }兩個(gè)mb()內(nèi)存屏障分別保證用戶回調(diào)先于 handler 地址寫入和handler 地址寫入先于后續(xù)操作可見避免競(jìng)態(tài)。這些步驟對(duì)應(yīng)文檔 Background 中目標(biāo)進(jìn)程通過(guò)mtspr(BESCR)啟用 EBB的硬件側(cè)描述。讀取與關(guān)閉 EBB 事件讀取可以對(duì) EBB 事件執(zhí)行read()但結(jié)果是毫無(wú)意義的。因?yàn)橹袛啾恢苯油哆f給用戶進(jìn)程內(nèi)核無(wú)法統(tǒng)計(jì)該事件只會(huì)返回一個(gè)垃圾值junk value。read()在此的唯一用途就是上一節(jié)所述的調(diào)度判定EOF 表示未調(diào)度。關(guān)閉用完后像常規(guī)事件一樣close()即可。如果這是最后一個(gè) EBB 事件PMU 將被解除 EBB 配置之后不再投遞任何 PMU EBB。selftests 中的 close_clears_pmcc_test.c 專門驗(yàn)證了關(guān)閉事件后用戶態(tài)對(duì) PMC 的讀/寫權(quán)限MMCR0[PMCC]被正確回收防止權(quán)限殘留。EBB 處理程序以中斷處理器的風(fēng)格編寫用戶態(tài)代碼EBB 處理程序本質(zhì)上是普通用戶空間代碼但必須以中斷處理程序的風(fēng)格編寫進(jìn)入 handler 時(shí)所有寄存器都是活的possibly live在調(diào)用任何其它代碼之前必須先把它們保存起來(lái)。具體怎么保存由程序自行決定對(duì) C 程序而言一個(gè)相對(duì)簡(jiǎn)單的方案是在棧上建立一個(gè)中斷幀interrupt frame并保存寄存器。倉(cāng)庫(kù)中的 ebb_handler.S 給出了完整的參考實(shí)現(xiàn)其框架極具教學(xué)價(jià)值棧布局設(shè)計(jì)注釋中繪制的示意圖在用戶棧上依次分配 Red zone / ABI Gap、VSR0–VSR63 與 VSCR/FSCR、GPR r0–r31 及 XER/CTR/LR/CCR 保存區(qū)、調(diào)用者幀總計(jì)#define SAVE_AREA ((NR_GPR NR_SPR) * 8 (NR_VSR * 16)) #define CALLER_FRAME 112 #define STACK_FRAME (ABIGAP SAVE_AREA CALLER_FRAME)入口處理stdu r1,-STACK_FRAME(r1)壓棧建幀然后依次保存 GPRSAVE_GPR(n)、XER/CTR/LR/CCR再通過(guò)stxvd2x保存全部 64 個(gè) VSR 向量寄存器與 FSCR/VSCR 狀態(tài)位。之后故意用lis n,0xaaaa破壞TRASH除 r1、r13 外的所有 GPR——這驗(yàn)證了 EBB handler 不能依賴任何調(diào)用者寄存器的存活值是所有寄存器都可能是活的的直接體現(xiàn)。調(diào)用用戶回調(diào)恢復(fù) TOC 指針RESTORE_TOC后調(diào)用 C 側(cè)鉤子ebb_hook而 ebb.c 中void ebb_hook(void) { if (ebb_user_func) ebb_user_func(); }將控制權(quán)轉(zhuǎn)交給用戶注冊(cè)的standard_ebb_callee之類的回調(diào)。返回路徑按相反順序恢復(fù) FSCR、VSCR、全部 VSR、XER/CTR/LR/CCR、GPR最后addi r1,r1,STACK_FRAME撤銷棧幀并以特殊指令返回#define RFEBB .long 0x4c0009240x4c000924即rfebbReturn From Event Based Branch指令編碼。它從 EBBRR 恢復(fù)被打斷的指令流這正是 EBB 與普通中斷最大的不同——由硬件完成上下文切換的返回?zé)o需內(nèi)核參與。standard_ebb_calleeebb.c展示了處理邏輯的典型寫法讀SPRN_BESCR檢查BESCR_PMEOPMU EBB 溢出位無(wú)溢出則記為 spurious偽中斷否則遞增ebb_count、讀取 MMCR0、遍歷所有啟用的 PMC 用count_pmc()累加計(jì)數(shù)值最后調(diào)用reset_ebb()復(fù)位void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask) { u64 val; /* 2) clear MMCR0[PMAO] - docs say BESCR[PMEO] should do this */ /* 3) set MMCR0[PMAE] - docs say BESCR[PME] should do this */ val mfspr(SPRN_MMCR0); mtspr(SPRN_MMCR0, (val ~mmcr0_clear_mask) | MMCR0_PMAE); /* 4) clear BESCR[PMEO] */ mtspr(SPRN_BESCRR, BESCR_PMEO); /* 5) set BESCR[PME] */ mtspr(SPRN_BESCRS, BESCR_PME); /* 6) rfebb 1 - done in our caller */ }這個(gè)序列恰好對(duì)應(yīng)硬件手冊(cè)對(duì) EBB handler 退出前的復(fù)位要求清除MMCR0[PMAO]/FC凍結(jié)標(biāo)志、重新置位MMCR0[PMAE]、清BESCR[PMEO]、置BESCR[PME]隨后由匯編層執(zhí)行rfebb。fork 語(yǔ)義EBB 不跨進(jìn)程繼承文檔明確兩條 fork 規(guī)則事件不繼承EBB 事件不隨fork()繼承。子進(jìn)程若想使用 EBB必須為自己重新打開事件。寄存器狀態(tài)清零BESCR/EBBHR/EBBRR中的 EBB 狀態(tài)在fork()時(shí)被清除。selftests 中 fork_cleanup_test.c 與 ebb_on_child_test.c 分別驗(yàn)證了fork 后子進(jìn)程 EBB 狀態(tài)被清理與子進(jìn)程自愿重新初始化 EBB兩條路徑ebb_on_willing_child_test.c 則測(cè)試了配合協(xié)作的子進(jìn)程場(chǎng)景。內(nèi)核調(diào)度實(shí)現(xiàn)pinned/exclusive 如何在 PMU 上落地文檔描述的互斥語(yǔ)義在 arch/powerpc/perf/core-book3s.c 中有完整的調(diào)度期實(shí)現(xiàn)。首次掛入時(shí)的used_ebb標(biāo)記——ebb_event_add()static void ebb_event_add(struct perf_event *event) { if (!is_ebb_event(event) || current-thread.used_ebb) return; /* * IFF this is the first time weve added an EBB event, set * PMXE in the user MMCR0 so we can detect when its cleared by * userspace. We need this so that we can context switch while * userspace is in the EBB handler (where PMXE is 0). */ current-thread.used_ebb 1; current-thread.mmcr0 | MMCR0_PMXE; }首次添加 EBB 事件時(shí)內(nèi)核在用戶態(tài)可見的 MMCR0 中置位MMCR0_PMXE性能監(jiān)控異常使能目的是在用戶態(tài)處于 EBB handlerPMXE 為 0時(shí)也能正確完成上下文切換。調(diào)度切入ebb_switch_in()——當(dāng) PMU 以 EBB 模式切入時(shí)向 MMCR0 追加多個(gè)用戶態(tài)可訪問(wèn)位reg.h 定義/* Enable EBB and read/write to all 6 PMCs and BHRB for userspace */ mmcr0 | MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC_U6;MMCR0_EBE0x00100000Event based branch enableEBB 主開關(guān)MMCR0_BHRBA0x00200000允許用戶態(tài)訪問(wèn) BHRB分支歷史記錄緩沖MMCR0_PMCC_U60x00080000PMC1–6 對(duì)用戶態(tài)可讀寫。隨后把用戶態(tài)保存的 SIAR/SIER/SDAR 與 MMCR2 合并寫回mtspr并為 POWER10/12 等 PPMU_ARCH_31 平臺(tái)追加 MMCR3/SIER2/SIER3。注釋明確合并語(yǔ)義用戶 MMCR2 只能置位凍結(jié)計(jì)數(shù)器而不能清位若任務(wù)需要自行清位解凍計(jì)數(shù)器則不應(yīng)在事件上設(shè)置exclude_xxx而應(yīng)由用戶態(tài)全權(quán)管理 MMCR2。調(diào)度切出ebb_switch_out()——當(dāng)MMCR0_EBE置位時(shí)把 SIAR/SIER/SDAR、MMCR0僅保留MMCR0_USER_MASK FC|PMXE|PMAO位、MMCR2 等保存回current-thread供下次切回時(shí)恢復(fù)#define MMCR0_USER_MASK (MMCR0_FC | MMCR0_PMXE | MMCR0_PMAO) #define MMCR2_USER_MASK 0x4020100804020000UL /* (FC1P|FC2P|FC3P|FC4P|FC5P|FC6P) */ #define SIER_USER_MASK 0x7fffffUL這些掩碼表明EBB 模式下用戶態(tài)只對(duì) MMCR0/MMCR2/SIER 的用戶相關(guān)子集擁有可見性內(nèi)核與用戶態(tài)各自維護(hù)自己的那部分狀態(tài)上下文切換時(shí)按位合并——這是 EBB 能在零內(nèi)核介入下工作的關(guān)鍵機(jī)制。POWER8E 硬件缺陷補(bǔ)償pmao_restore_workaround——該函數(shù)處理 POWER8E 的一個(gè)已知 PMU 上下文切換缺陷計(jì)數(shù)器溢出后 PMXE 被清、MMCR0 置 FC/PMAO但 PMU 異常可能延遲到達(dá)若在此之前發(fā)生上下文切換異常會(huì)丟失。解決方式是檢測(cè)PMAO置位而PMAO_SYNC未置位的狀態(tài)EBB 場(chǎng)景還要求BESCR_GE置位通過(guò)讓 PMC6 逼近溢出制造一個(gè)新的待決異常待返回用戶態(tài)時(shí)再投遞。這一實(shí)現(xiàn)細(xì)節(jié)表明EBB 在真實(shí)硬件上的可靠性依賴內(nèi)核與硬件的協(xié)同補(bǔ)償并非簡(jiǎn)單的全硬件路徑。測(cè)試驗(yàn)證selftests 中的 EBB 覆蓋矩陣內(nèi)核為 EBB 提供了完整的自測(cè)套件位于 tools/testing/selftests/powerpc/pmu/ebb/Makefile 定義了全部 25 個(gè)測(cè)試程序覆蓋了本文討論的幾乎所有語(yǔ)義測(cè)試程序驗(yàn)證要點(diǎn)reg_access_test/regs_access_pmccext_test用戶態(tài)對(duì) EBB 相關(guān) SPR 與 PMC 的讀寫訪問(wèn)event_attributes_test創(chuàng)建 EBB 事件的屬性約束pinned/exclusive、禁用屬性等正反用例cycles_test最基本的 EBB 周期計(jì)數(shù)cycles_with_freeze_test與計(jì)數(shù)器凍結(jié)MMCR0[FC]交互cycles_with_mmcr2_test用戶態(tài) MMCR2 凍結(jié)位語(yǔ)義pmc56_overflow_testPMC5/6 溢出路徑ebb_vs_cpu_event_test/cpu_event_vs_ebb_testEBB 與 CPU 級(jí)事件的互斥cpu_event_pinned_vs_ebb_testEBB 與 pinned CPU 事件同時(shí)請(qǐng)求時(shí)的仲裁先啟用者勝task_event_vs_ebb_test/task_event_pinned_vs_ebb_testEBB 與任務(wù)級(jí)事件的互斥multi_counter_test多 PMC 同時(shí)計(jì)數(shù)multi_ebb_procs_test多進(jìn)程 EBBpmae_handling_testPMAE/PMAO 處理close_clears_pmcc_testclose 后回收用戶態(tài) PMC 權(quán)限instruction_count_test指令計(jì)數(shù)事件fork_cleanup_testfork 后 EBB 狀態(tài)清理ebb_on_child_test/ebb_on_willing_child_test子進(jìn)程 EBB 場(chǎng)景back_to_back_ebbs_test連續(xù) EBB 觸發(fā)lost_exception_test異常丟失場(chǎng)景no_handler_test未注冊(cè) handler 的行為測(cè)試統(tǒng)一以 64 位編譯CFLAGS -m64并顯式關(guān)閉 PIE-no-pie因?yàn)?ebb_handler.S 中的匯編代碼與絕對(duì)地址處理依賴非 PIE 布局。運(yùn)行這些測(cè)試前可通過(guò)ebb_is_supported()檢查PPC_FEATURE2_EBBhwcap2 位見 ebb.c確認(rèn)硬件支持 EBB——EBB 至少要求 POWER8 及以后的處理器。這一 hwcap 檢查與內(nèi)核側(cè)PPMU_ARCH_207S能力標(biāo)志is_ebb_event互為印證文檔所述的 Power ISA v2.07 特性在軟件棧中由這兩個(gè)地方共同把關(guān)。小結(jié)EBB 的完整工作鏈路綜合文檔與源碼一條 PMU EBB 的完整生命周期可歸納為用戶態(tài)初始化設(shè)置attr.configbit 63PERF_EVENT_CONFIG_EBB_SHIFTleader 設(shè)置pinnedexclusive組內(nèi)統(tǒng)一 EBB 意愿指定 PMC通過(guò)perf_event_open()pid當(dāng)前任務(wù)創(chuàng)建任務(wù)級(jí)事件——內(nèi)核ebb_event_check()校驗(yàn)全部約束用戶態(tài)硬件準(zhǔn)備mtspr(SPRN_EBBHR, handler)注冊(cè)處理程序mtspr(SPRN_BESCR, GE|PME)全局使能啟用與確認(rèn)ioctl/prctl 啟用事件后read()返回非 EOF 才表明事件已調(diào)度上 PMUpinned/exclusive 互斥仲裁事件觸發(fā)PMC 溢出時(shí)硬件直接分支到 EBBHR 指向的用戶態(tài)地址處理程序如 ebb_handler.S 的框架保存全部寄存器、讀取 BESCR/PMC、復(fù)位 MMCR0/BESCR 后以rfebb返回內(nèi)核兜底調(diào)度切入/切出時(shí)通過(guò)ebb_switch_in()/ebb_switch_out()按位合并用戶態(tài)與內(nèi)核態(tài)的 MMCR0/MMCR2/SIER 狀態(tài)并以pmao_restore_workaround()補(bǔ)償 POWER8E 硬件缺陷清理close()最后一個(gè) EBB 事件后 PMU 退出 EBB 模式fork()不會(huì)繼承任何 EBB 狀態(tài)子進(jìn)程需重新初始化。EBB 的價(jià)值在于把性能監(jiān)控中斷的投遞路徑從內(nèi)核中斷 → 采樣 → 信號(hào)/通知縮短為硬件 → 用戶態(tài) handler為低延遲、高精度的用戶態(tài)自監(jiān)控例如運(yùn)行時(shí)剖析器、硬件事件驅(qū)動(dòng)的自適應(yīng)優(yōu)化提供了 Linux 下的官方支持路徑。對(duì)開發(fā)者而言pmu-ebb.rst 是 API 層面的權(quán)威指南而 core-book3s.c 與 selftests 套件則分別提供了實(shí)現(xiàn)級(jí)與可運(yùn)行示例級(jí)的完整參照。【免費(fèi)下載鏈接】linuxLinux kernel source tree項(xiàng)目地址: https://gitcode.com/GitHub_Trending/li/linux創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考