最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一文看懂為什么mmap之后訪問(wèn)地址仍然發(fā)生了缺頁(yè)異常?

2022-11-04 15:30 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

問(wèn)題簡(jiǎn)述

在筆者的開發(fā)平臺(tái)上,應(yīng)用程序使用ION申請(qǐng)cma內(nèi)存,并用mmap映射到用戶地址空間去做寫操作。

重點(diǎn)代碼摘要如下:


客戶希望提高

node->var = some_value;

這里的訪問(wèn)效率(實(shí)際代碼要復(fù)雜些,是申請(qǐng)了一個(gè)大數(shù)組并往里循環(huán)讀寫數(shù)據(jù))。

第一輪分析

首先用perf分析應(yīng)用程序行為,發(fā)現(xiàn)程序在運(yùn)行時(shí)產(chǎn)生了不少page fault,感覺是mmap之后內(nèi)核并沒有建立映射,而是在第一次訪問(wèn)此地址時(shí),產(chǎn)生fault in所致。

第一個(gè)想法

首先想到優(yōu)化點(diǎn)是:用MAP_POPULATE強(qiáng)制在mmap系統(tǒng)調(diào)用里面把所有的頁(yè)面都fault in,這樣后面訪問(wèn)就不會(huì)產(chǎn)生page fault而耽誤時(shí)間了。因?yàn)閜age fault不管是在前還是在后總會(huì)發(fā)生,這個(gè)優(yōu)化思路其實(shí)只是讓這段時(shí)間集中挪到了訪問(wèn)數(shù)據(jù)之前。但看了一下mmap的手冊(cè),說(shuō)到MAP_POPULATE只能針對(duì)于MAP_PRIVATE映射(見mmap手冊(cè)),比如用匿名頁(yè)建立的映射,而此處因?yàn)槭荕AP_SHARED,無(wú)法用MAP_POPULATE,故此方案作罷。

第二個(gè)想法

用ftrace跟蹤了一下ion代碼,發(fā)現(xiàn)mmap已經(jīng)調(diào)用了remap_pfn_range來(lái)建立頁(yè)面映射,代碼路徑如下:

mmap => el0_sync => el0_sync_handler => el0_svc => do_el0_svc => el0_svc_common.constprop.4 => __arm64_sys_mmap => ksys_mmap_pgoff => vm_mmap_pgoff => do_mmap => mmap_region => dma_buf_mmap_internal => ion_dma_buf_mmap => ion_heap_map_user => remap_pfn_range

也就是說(shuō),從代碼路徑看,在mmap系統(tǒng)調(diào)用中,用戶頁(yè)已經(jīng)全都建立好了,所謂的fault in其實(shí)并不存在。那么問(wèn)題來(lái)了,既然不存在fault in,為什么還是會(huì)產(chǎn)生page fault呢?


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ? ?


轉(zhuǎn)機(jī)

因?yàn)榇藛?wèn)題是在換了內(nèi)核到5.10之后暴露出來(lái)的,嘗試在舊內(nèi)核4.19上嘗試同樣的代碼。

同樣代碼運(yùn)行在4.19內(nèi)核上,該寫操作的效率明顯高于5.10內(nèi)核。對(duì)比由perf stat觀測(cè)得出:



也就是說(shuō),4.19上面代碼如預(yù)期運(yùn)行,mmap時(shí)后就不再有page fault,但5.10上卻發(fā)生了page fault。

問(wèn)題就轉(zhuǎn)變成了:為什么remap_pfn_range之后仍發(fā)生了page fault?

分析remap_pfn_range行為發(fā)現(xiàn)應(yīng)該不是這里的問(wèn)題,那么,或許這個(gè)page fault不是缺頁(yè)異常,而是別的page fault? 想到這一層后,繼續(xù)對(duì)比4.19與5.10內(nèi)核行為。

問(wèn)題原因的要素分析

跳過(guò)冗長(zhǎng)的debug過(guò)程,直接說(shuō)5.10內(nèi)核在筆者平臺(tái)上造成此問(wèn)題的根本原因,原因由這幾個(gè)要素構(gòu)成:

  1. mmap在使用ION的時(shí)候,需要用參數(shù)MAP_SHARED

  • 此參數(shù)最終會(huì)傳導(dǎo)至ARM64 arch層在設(shè)置相應(yīng)頁(yè)表時(shí),采用PAGE_SHARED聯(lián)合屬性

  • PAGE_SHARED聯(lián)合屬性,包含這樣兩個(gè)頁(yè)表基本屬性:PTE_RDONLY | PTE_DBM

  1. 根據(jù)ARMv8手冊(cè),PTE_RDONLY | PTE_DBM 兩個(gè)屬性疊加,根據(jù)另一個(gè)系統(tǒng)寄存器的不同配置,會(huì)有兩種不同硬件處理的情況:二選一

  • 系統(tǒng)寄存器TCR_EL1.HD=1產(chǎn)生的效果是:在第一次寫操作訪問(wèn)該頁(yè)面時(shí),CPU會(huì)自動(dòng)更新頁(yè)面的RO屬性為RW,并不產(chǎn)生permission fault

  • 系統(tǒng)寄存器TCR_EL1.HD=0產(chǎn)生的效果是:在第一次寫操作訪問(wèn)該頁(yè)面時(shí),CPU不會(huì)自動(dòng)更新頁(yè)面的RO屬性為RW,而會(huì)產(chǎn)生一次permission fault,這個(gè)fault需要由操作系統(tǒng)去軟件更新為RW,它的主要目的,是為了讓操作系統(tǒng)跟蹤頁(yè)表第一次寫訪問(wèn)。

  1. 在筆者的內(nèi)核編譯中,系統(tǒng)寄存器TCR_EL1.HD=0,也就是走的B路線。

  • 之所以編譯會(huì)讓該位配置為0,是因?yàn)樾枰獙?shí)施一個(gè)CPU erratum的軟件規(guī)避 :Cortex-A55: 1024718: Update of DBM/AP bits without break before make might result in incorrect update,表現(xiàn)為內(nèi)核配置項(xiàng)CONFIG_ARM64_ERRATUM_1024718

  • CPU erratum是那些ARM core IP在設(shè)計(jì)時(shí)的缺陷所致的CPU硬件bug,因?yàn)镮P已經(jīng)集成在市面上的SoC里流片,不可能重新設(shè)計(jì),只能通過(guò)軟件做一些規(guī)避,這些規(guī)避方法,均記錄在ARM的官方Errata文檔(CPU勘誤手冊(cè))里。

  • 以A55來(lái)說(shuō),此Erratum編號(hào)為1024718,影響范圍是所有版本號(hào)<=r2p0的Cortex-A55 core IP,規(guī)避辦法是設(shè)置TCR_EL1.HD=0

  • 筆者平臺(tái)的CPU版本號(hào),正好是r2p0,恰好在此Erratum的范圍內(nèi),必須實(shí)施CONFIG_ARM64_ERRATUM_1024718

綜上,5.10內(nèi)核,因?yàn)樯鲜龅娜恳芈?lián)合,就產(chǎn)生了這個(gè)permission page fault 。

相關(guān)疑問(wèn)與解答

問(wèn):為什么4.19沒有此問(wèn)題

答:

4.19具備其余所有要素,只缺要素1.b PAGE_SHARED聯(lián)合屬性,包含這樣兩個(gè)頁(yè)表基本屬性:PTE_RDONLY | PTE_DBM

4.19內(nèi)核里,PAGE_SHARED聯(lián)合屬性,缺少PTE_RDONLY。

以下為4.19與5.10的 PAGE_SHARED宏對(duì)比:

4.19內(nèi)核 #define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)

5.10內(nèi)核 #define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)

5.10內(nèi)核多出來(lái)的PTE_RDONLY,再加上使得上述permission page fault 觸發(fā)了。

問(wèn):為什么5.10要引入PTE_RDONLY屬性?

答:

5.10對(duì)PTE_RDONLY引入,是ARM官方maintainer的刻意行為,源于commit:

https://github.com/torvalds/linux/commit/aa57157be69fb599bd4c38a4b75c5aad74a60ec0 arm64: Ensure VM_WRITE|VM_SHARED ptes are clean by default

從該commit描述看,對(duì)此的引入是合理的,因?yàn)橐胝哳A(yù)期配置了TCR_EL1.HD=1,即問(wèn)題要素2.A)的路徑,由CPU硬件自動(dòng)處理頁(yè)表項(xiàng)RO轉(zhuǎn)RW。只有當(dāng)諸如CONFIG_ARM64_ERRATUM_1024718這樣的CPU erratum軟件規(guī)避開啟時(shí),因?yàn)橄到y(tǒng)寄存器TCR_EL1.HD=0,才會(huì)落入到**permission page fault** 的情景中。而這個(gè)是commit原作者可能未注意到的情況。實(shí)測(cè)發(fā)現(xiàn),去掉此erratum,page fault也確實(shí)消失了。

問(wèn)題解決方案

目前采用的辦法是一個(gè)workaround(而非fix):?jiǎn)伟裀AGE_SHARED屬性回退為與4.19內(nèi)核一致(參考前文提到的那個(gè)commit)。實(shí)測(cè)性能與4.19幾乎無(wú)差別了:


因?yàn)槟莻€(gè)ARM官方的commit是社區(qū)深思熟慮的刻意行為,回退并不現(xiàn)實(shí),根本解決辦法,應(yīng)該是給出一個(gè)綜合的patch,使得方方面面的情況都照顧到。

問(wèn)題回顧

這個(gè)bug卡筆者最長(zhǎng)的時(shí)間,其實(shí)是在這一條:為什么remap_pfn_range之后仍發(fā)生了page fault?因?yàn)楣P者先入為主的觀念,把所有page fault都當(dāng)成了缺頁(yè)異常,而沒有第一時(shí)間想到permission fault的可能,導(dǎo)致浪費(fèi)了大量時(shí)間來(lái)分析remap_pfn_range的行為,雖然代碼邏輯整理了不少,但一直沒能進(jìn)入核心要點(diǎn)。這一點(diǎn)突破以后,后面的分析和解決就是水到渠成的事情了。





一文看懂為什么mmap之后訪問(wèn)地址仍然發(fā)生了缺頁(yè)異常?的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
天峻县| 永年县| 安岳县| 东海县| 桓台县| 山西省| 彭水| 乌兰察布市| 集安市| 余姚市| 和平区| 武邑县| 绥化市| 东宁县| 惠安县| 柳林县| 沂水县| 平陆县| 雷山县| 全南县| 乌拉特后旗| 濮阳市| 肥西县| 汝南县| 仪陇县| 富锦市| 东丰县| 年辖:市辖区| 夏津县| 婺源县| 北流市| 太仓市| 新野县| 久治县| 乌海市| 当阳市| 罗城| 南江县| 兴化市| 湖南省| 波密县|