国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

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

【知乎】x86架構(gòu)&linux內(nèi)核系列(五-六)

2023-12-03 07:00 作者:失傳技術(shù)  | 我要投稿

x86架構(gòu)&linux內(nèi)核系列(五) 番外篇------聊聊寄存器和Linux crash分析


雪瀑牽裳


IT 老棒槌

8 人贊同了該文章

呃,上一篇結(jié)尾后,工作上的事情讓我不能分心繼續(xù)寫(xiě)專(zhuān)題。
既然我們已經(jīng)聊了一下CPU的core,所以我們就可以初步說(shuō)說(shuō)寄存器了。而寄存器又和os的crash分析密切相關(guān)。因此,我們恰似站在一個(gè)叉路口,雖然我們的計(jì)劃仍然是先沿著intel x86架構(gòu)這個(gè)方向走往下走,但是也不妨站在這個(gè)岔路口歇歇,向另外的方向看linux crash分析的風(fēng)景和故事。
一、啥是寄存器(register)
寄存器位于CPU內(nèi)部,用于存放程序執(zhí)行中用到的數(shù)據(jù)和指令,CPU從寄存器中取數(shù)據(jù),相比從內(nèi)存中取快得多。
95~99年我上大學(xué)時(shí)學(xué)計(jì)算機(jī)結(jié)構(gòu),那是我還真的把寄存器當(dāng)作CPU內(nèi)部的“器”。

而現(xiàn)在,我越來(lái)越喜歡將寄存器認(rèn)為是:在CPU內(nèi)部有專(zhuān)用的快速存儲(chǔ)空間。Intel嚴(yán)格規(guī)定了這些快速存儲(chǔ)空間內(nèi)每個(gè)地址的用途。而且Intel為了好理解,將空間內(nèi)特定地址的幾個(gè)字節(jié),起了個(gè)好理解的名字,這個(gè)名字就是寄存器的名字。
——所以,寄存器實(shí)際上就是CPU內(nèi)部的專(zhuān)用快速存儲(chǔ)空間內(nèi),某幾個(gè)字節(jié)的地址(可以表示為某基址加上不同的偏移量(這個(gè)“偏移量”就是 intel eds 里總是伴隨寄存器出現(xiàn)的、讓人不好理解的一個(gè)詞,呃,offset?。?strong>

一個(gè)物理CPU/socket內(nèi)部,有cores部分和uncore moudules部分。 CPU里的寄存器有太多太多,intel eds第二本 3200頁(yè),第三本 900頁(yè),講的是CPU socket uncore modules的各個(gè)寄存器+core里的MCA狀態(tài)寄存器。至于core里的程序寄存器,我還沒(méi)有看過(guò)相關(guān)的文檔呢。估計(jì)怎么著也有幾百頁(yè)吧。所以這么看skx CPU 的全部寄存器資料,應(yīng)該至少有4000頁(yè)了。
——這4000頁(yè)就相當(dāng)于X86知識(shí)體系結(jié)構(gòu)的字典。

又要講個(gè)小故事了:半年前我曾接到一個(gè)指示,讓我先看一份英文原版的、據(jù)說(shuō)有個(gè)十多頁(yè)的intel的文檔,然后用個(gè)把月時(shí)間整理出個(gè)診斷工具出來(lái)。這話說(shuō)的是輕描淡寫(xiě),但是我一打開(kāi)那個(gè)文檔,嚯!就是他娘的intel eds 第二卷——全英文的3180頁(yè)!而且公司內(nèi)部也沒(méi)有intel x86架構(gòu)入門(mén)培訓(xùn)資料讓我先鋪墊鋪墊入個(gè)門(mén)。這事兒惡心的,就像一大仙兒拍下腦袋,扔給一個(gè)小學(xué)生一本新華字典,讓他自己學(xué)著寫(xiě)作文……不過(guò)還是要感謝司內(nèi)的這些仙兒們,雖然他們只負(fù)責(zé)拉通,但最終還是激勵(lì)了我,通過(guò)各種圈內(nèi)渠道,補(bǔ)全自己的知識(shí)庫(kù),做了給人的技術(shù)積累。當(dāng)然,這事兒也讓我對(duì)某些所謂浸淫多年x86領(lǐng)域的群體,又有了一個(gè)新認(rèn)識(shí)。

下面是我所接觸過(guò)的三大類(lèi)寄存器。

二、core內(nèi)部和操作系統(tǒng)、crash分析相關(guān)的寄存器

這部分寄存器包括:通用寄存器 和 棧寄存器。

(一)通用寄存器:

例如ax/bx/cx/dx/di/si這些,如果按照目前64位的說(shuō)法,這些寄存器前面加上”r”或“e”表示64位。那么以上這些寄存器就對(duì)應(yīng)稱(chēng)為:rax/rbx/rcx/rdx/rdi/rsi 。
另外還有一堆的rXX,XX代表數(shù)字。
以上這些寄存器在程序指令中,用于存儲(chǔ)變量(其實(shí)是變量所在的棧地址)并用于變量賦值/運(yùn)算。其中,有一些寄存器也有一些特定用法的,例如:
Rdi和rsi,常用于 函數(shù)外部向函數(shù)內(nèi)部傳參。
rax,常用與函數(shù)返回值。

假設(shè)有一天,你有幸進(jìn)行l(wèi)inux crash分析,那么使用crash工具對(duì)嫌疑進(jìn)程進(jìn)行反編譯,你所看到的冰山一角就是這個(gè)樣子滴:(里面有edx,rxx,rbp…)


然后對(duì)linux crash分析的大體過(guò)程就是:
1、你需要根據(jù)上圖反編譯出來(lái)的匯編語(yǔ)言中的寄存器的命令邏輯 對(duì)照 內(nèi)核C語(yǔ)言程序的指令邏輯,然后將二者邏輯完全印證理解;——邏輯流分析
2、然后再根據(jù)下面論述的Core 內(nèi)的數(shù)據(jù)棧,以及棧寄存器的值,找到C語(yǔ)言指令上下文、以及函數(shù)調(diào)用上下文中的變量、參數(shù)(其實(shí)在linux里,絕大部分參數(shù)都是結(jié)構(gòu)體)的變化和傳遞過(guò)程?!獢?shù)據(jù)流分析

是不是有點(diǎn)看不懂?
那就換個(gè)說(shuō)法:如果我們把Linux crash分析 對(duì)比 病人診斷 那么:
反編譯出來(lái)的匯編指令 對(duì)應(yīng)著 病人哼哼;
C語(yǔ)言指令上下文 對(duì)應(yīng)著 病理推斷;
變量的變化、尤其是函數(shù)傳參過(guò)程中參數(shù)的變化 對(duì)應(yīng)著 各項(xiàng)醫(yī)學(xué)儀器檢查結(jié)果;
Linux內(nèi)核知識(shí) 對(duì)應(yīng)著 人體組織結(jié)構(gòu)圖;
Crash分析案例庫(kù) 對(duì)應(yīng)著 醫(yī)院里的案例參考;

(想想看,操作系統(tǒng)crash分析的知識(shí)體系是不是呼之欲出了?)
——以上這五者,就構(gòu)成了 crash分析藝術(shù)。
所以有個(gè)redhat原廠專(zhuān)家在做技術(shù)講座的時(shí)候曾說(shuō)過(guò),不同的人分析同一個(gè)crash,有可能分析方向不同,分析過(guò)程不同,甚至,甚至最后的結(jié)論也有差異。但是單從crash分析過(guò)程講,可能每個(gè)人的分析都是有道理的?!跃陀昧怂囆g(shù)這個(gè)詞。因?yàn)樗囆g(shù)的形式是多樣的。
所以,如果沒(méi)有上面5個(gè)方面的基礎(chǔ),linux 專(zhuān)家抽個(gè)半天時(shí)間給你講crash分析,聽(tīng)眾也就是湊個(gè)熱鬧,開(kāi)個(gè)眼界,不明覺(jué)厲而已。

思考:
1、有哥們?cè)?jīng)問(wèn)我:你教我怎么分析redhat crash吧。當(dāng)時(shí)我該怎么回答?只能?chē)@氣啊。
2、有想象力的某些人,想讓我做個(gè)工具:這頭輸入crash dump文件,那頭直接出結(jié)果。我該怎么做?這可是未來(lái)的AI主題啊。
——嗯,在心底真的佩服無(wú)知者無(wú)畏。

(二)上下文相關(guān)寄存器:
在linux crash分析中常用,描述了進(jìn)程函數(shù)的棧數(shù)據(jù)結(jié)構(gòu)。

Crash分析常見(jiàn)以下三種:
Rbp/ebp寄存器:棧的基地址
rsp/esp寄存器:棧的當(dāng)前地址也有叫棧頂?shù)模?br>rip寄存器:當(dāng)前執(zhí)行指令的下一條指令;


進(jìn)程空間圖先放這里,以后到redhat crash分析系列來(lái)講:

上圖0x015fbfff就算rbp了;0x015fa878就算rsp了;Current箭頭 (靠近0x015fa000)的地方,右側(cè),相當(dāng)于當(dāng)前的那條代碼),就算rip了;

其實(shí)這個(gè)圖很粗,首先這是32位用戶態(tài)的進(jìn)程數(shù)據(jù)結(jié)構(gòu),地址格式都有些過(guò)時(shí)了。另外這幅圖粗的連segment都沒(méi)列出來(lái)。先這么看吧。

曾經(jīng)某case的 “嫌疑進(jìn)程”在把系統(tǒng)搞死之前留下這樣的的“遺書(shū)”——又叫call trace:

——可以自己先猜猜,里面都暗示了啥,參悟一下吧,以后另一個(gè)系列會(huì)細(xì)講。

看上面的圖片,ffffxxxxxxxxxxxx打頭的以及ffffffffxxxxxxxx等一片片Hex數(shù)字像天書(shū)。

呃,如果你想明白這些天書(shū)代表什么意思,最好搞明白以下機(jī)制和數(shù)據(jù)結(jié)構(gòu):

x86服務(wù)器架構(gòu) 系統(tǒng)地址映射、

Linux 64位空間地址結(jié)構(gòu)、

用戶態(tài)/內(nèi)核態(tài)、

內(nèi)核態(tài)下的虛擬地址與物理地址的映射、

Page_offset與text_offset。


而以上這些仍只是基礎(chǔ),接下來(lái)還是會(huì)對(duì) linux crash 分析感到云里霧里的。那我就再講個(gè)故事、再類(lèi)比一下linux crash分析,又叫vmcore分析:
話說(shuō)一頭豬媽媽?zhuān)a(chǎn)下豬仔仔后,突然暈過(guò)去了——linux crash了。
然后一個(gè)獸醫(yī)來(lái)了 ——linux專(zhuān)家響應(yīng)這個(gè)case。
這位獸醫(yī)能聽(tīng)懂豬的語(yǔ)言——專(zhuān)家要懂點(diǎn)匯編。
這位獸醫(yī)當(dāng)然也能懂人話——專(zhuān)家要懂C語(yǔ)言。
這位獸醫(yī)熟讀本山大叔的著作:《論母豬的產(chǎn)后護(hù)理》——專(zhuān)家有深厚的linux內(nèi)核知識(shí)。
這位獸醫(yī)是有十多年經(jīng)驗(yàn)的當(dāng)?shù)仡^牌獸醫(yī)——專(zhuān)家有豐富的案例庫(kù)供查詢(xún)。
然后獸醫(yī)根據(jù)這頭豬醒了以后的哼哼唧唧,詳細(xì)還原了豬媽媽暈倒前后每一個(gè)細(xì)節(jié)和過(guò)程——這就是crash文件解析。
然后獸醫(yī)又發(fā)現(xiàn),豬媽媽產(chǎn)下的豬仔仔居然有點(diǎn)像小象——其他的外部日志和異常。

最終獸醫(yī)得出以下結(jié)論:
由于豬媽媽生下了一頭長(zhǎng)的像小象的豬仔仔,怕豬爸爸生氣,導(dǎo)致心理壓力過(guò)大,然后茶不思飯不想,出現(xiàn)了低血糖現(xiàn)象,所以暈了過(guò)去……
這大概就是crash分析了。

現(xiàn)在,只能通過(guò)類(lèi)比來(lái)感受一下了。具體的,以后若開(kāi)linux內(nèi)核專(zhuān)題再講。

好了,linux的crash的風(fēng)景看完、故事聽(tīng)完,發(fā)現(xiàn)intel CPU x86 架構(gòu)仍是基礎(chǔ)。

所以我們還是繼續(xù)返回到intel CPU x86 架構(gòu)吧。

三、Socket Core MSR寄存器
用于MCE 處理,記載了MCE發(fā)生時(shí),CPU,MEM各個(gè)硬件的狀態(tài)和故障指向。在講完所有的CPU uncore modules 后,再開(kāi)始詳細(xì)的聊這部分內(nèi)容。
MCE是整個(gè)x86診斷體系的基礎(chǔ),是服務(wù)器診斷ts的重要組成部分。

四、Socket uncore部分的CSR 寄存器
用于cpu uncore 部件的運(yùn)行以及狀態(tài)記錄。常用與高級(jí)診斷。
1、 和MCE結(jié)合,判斷multi MCE或Nest MCE的 root cause。
2、 如果沒(méi)有出現(xiàn)MCE,就要通過(guò)CSR判斷是否出現(xiàn)了更嚴(yán)重的IERR,以及原因。
在講完所有的MCA寄存器后,再開(kāi)始詳細(xì)的聊這部分內(nèi)容。

好了,本次的正式內(nèi)容又結(jié)束了。

有位哥哥,在朋友圈里轉(zhuǎn)發(fā)我的技術(shù)文章時(shí),吹噓我是IT圈里的文藝青年。雖然吹的不是太走心,但是在這里,弟弟我還是要頭拱地配合一下的。
上周某個(gè)夜晚,一個(gè)人聽(tīng)了首老歌《董小姐》,很有感覺(jué)。于是就順著感覺(jué)寫(xiě)了下面長(zhǎng)短句。

聽(tīng)《董小姐》
今晚,
聽(tīng)董小姐的歌。
慵懶的囈語(yǔ),
仿佛指尖上玩火。
半杯紅酒,
酡然揮不去 有些頹廢,
不知從前往事,
還能挽留幾絲余味?
輕嗅手中煙草,
假裝戒了好多年,
安靜與躁動(dòng)之間,
無(wú)言對(duì)無(wú)眠。
一丟丟放肆,
才要點(diǎn)燃,
卻已是結(jié)尾,
溫柔斷弦。

編輯于 2019-05-14 21:22

「真誠(chéng)贊賞,手留余香」

還沒(méi)有人贊賞,快來(lái)當(dāng)?shù)谝粋€(gè)贊賞的人吧!

x86-64


我眼中的x86地圖,聊聊“”地址”那些事兒


雪瀑牽裳


IT 老棒槌

關(guān)注他

23 人贊同了該文章

一直想寫(xiě),卻一直不知道該如何來(lái)寫(xiě)這篇關(guān)于“地址”的文。

“地址”這個(gè)概念似乎很簡(jiǎn)單,稍有計(jì)算機(jī)基礎(chǔ)的人都會(huì)接觸。

這個(gè)概念又很混亂。網(wǎng)上各種文章,張冠李戴的毛病是一種,常常隨意省略概念前的主語(yǔ)、定語(yǔ)的毛病又是一種。所以通讀文章的時(shí)候,常搞得人精神分裂。

然而地址這個(gè)概念又無(wú)處不在,幾乎貫穿了我所接觸的技術(shù)領(lǐng)域:從某個(gè)硬件module(例如CPU,DIMM/IMC,cache,mmu,iommu)向上到不硬不軟的bios/uefi,乃至軟件OS內(nèi)核,甚至再向上到達(dá)更軟的應(yīng)用程序。

這個(gè)概念寫(xiě)起來(lái)委實(shí)不易。

因?yàn)橛?jì)算機(jī)中的“地址”這個(gè)概念,依據(jù)不同的“空間層次”或者說(shuō)“平面”,其實(shí)也分成好幾類(lèi)。

所以,當(dāng)我要寫(xiě)XXXX地址的時(shí)候,覺(jué)得必須先要把XXXX說(shuō)明白,然后才能講xxxx地址。
然后當(dāng)我另起一段想說(shuō)新的YYYY地址的時(shí)候,我又要先說(shuō)什么是YYYY……

所以本來(lái)計(jì)劃十多分鐘的技術(shù)貼,最后能洋洋灑灑寫(xiě)出另外一整套系列。

我又一直想寫(xiě)它,因?yàn)檫@個(gè)概念仿佛就是一個(gè)里程碑,或者是我腳下的重要階梯。
先前,正是因?yàn)槲也粩嗟睦斫膺@個(gè)概念、重復(fù)又重復(fù),所以才不知不覺(jué)的從硬件、從PCIE、從CPU一堆的MSR寄存器和CSR寄存器,跳進(jìn)了OS內(nèi)核。

今天嘗試寫(xiě)一下吧,歡迎進(jìn)入我的x86世界大觀。


本文所涉及的硬件平臺(tái)指的是Intel purley平臺(tái)以及Intel xeon skylake CPU;
操作系統(tǒng)缺省指的是linux。

想象一下,此時(shí)我正站在一個(gè)路口,這個(gè)路口稱(chēng)為x86硬件架構(gòu)。從這個(gè)路口往前往后往左往右看,都可以到達(dá)不同的地方。

有的方向,會(huì)進(jìn)入另外的專(zhuān)業(yè)領(lǐng)域,我們會(huì)嘗試走幾步看看風(fēng)景就好,然后回頭。因?yàn)槿羰亲叩搅税倩ㄉ钐?,又是另外一片世界了?br>
有的方向,我會(huì)嘗試一直走下去。



一、起點(diǎn):x86硬件架構(gòu)。路口的指示牌——物理地址

我先從腳下的x86硬件架構(gòu)說(shuō)起吧。我們站的地方,CPU的角度,就有一個(gè)核心的地址概念,那就是“物理地址”,有的時(shí)候又叫“系統(tǒng)地址”。


一說(shuō)起地址,好多人總是先將地址這個(gè)概念和主存(內(nèi)存條/DIMM/DRAM)的空間聯(lián)系起來(lái)。(這里不講制造工藝,所以“內(nèi)存條”,DIMM和DRAM在這里等同)。
其實(shí)我們不妨將目光的范圍放大一些:其實(shí)物理地址/系統(tǒng)地址是標(biāo)識(shí)整個(gè)計(jì)算機(jī)“空間”的(這里不包括IMC內(nèi)部的地址空間,和IO port 地址空間)。

而我們習(xí)慣說(shuō)的主存的空間,是計(jì)算機(jī)“整體空間”的一部分。當(dāng)然,主存的空間,是用戶人最容易直接感知到的空間,但主存的空間絕對(duì)不是計(jì)算機(jī)“空間”的全部。除了物理內(nèi)存的空間以外,重要的還有PCI(e)空間(pci和pcie不分了)、bios空間(ROM和ram就不分了)等等。

而物理地址這個(gè)概念,咱先從Intel的文檔里講起。
引用Intel的eds原文:
The Skylake Server is thenext generation of 64-bit, multi-core server processor builton 14-nm process technology.The processor supports up to 46 bits of physical?address space and 48 bits of virtual address space.

——skylake CPU,支持46位物理地址,48位虛擬地址。那么我們私下說(shuō),其實(shí)現(xiàn)在的“x86_64位架構(gòu)” 的說(shuō)法都不算嚴(yán)格,嚴(yán)格來(lái)說(shuō)應(yīng)該叫“32位enhanced”才對(duì):
1、Intel的CPU uncore-module的 CSR目前還都是32位的。
2、CPU中64位的MSR,命名還保持者IA32_的開(kāi)頭。
3、目前的尋址,物理達(dá)到46位,虛擬達(dá)到48位。

物理地址,是bios(其實(shí)正規(guī)文檔中說(shuō)的是firmware,但是我認(rèn)為就是bios)盤(pán)整了一遍計(jì)算機(jī)硬件后,將所有硬件的存儲(chǔ)空間(不算硬盤(pán)的存儲(chǔ)空間。在“主機(jī)架構(gòu)”的眼里,總把硬盤(pán)當(dāng)作沒(méi)有地位的通房大丫頭)進(jìn)行了統(tǒng)一的編址,這個(gè)編址就是物理地址。

Intel Purley平臺(tái)整個(gè)物理地址的樣子,Intel的文檔中給了下圖:



(仔細(xì)看看這個(gè)圖我們可以發(fā)現(xiàn),在某個(gè)架構(gòu)實(shí)現(xiàn)之初,就連專(zhuān)家的眼光都是局限的:專(zhuān)家認(rèn)為不可能超越的界限,幾年后卻被輕易的超越了,好尷尬啊。然后為了兼容,后面的架構(gòu)更新,就不得不像打補(bǔ)丁一樣對(duì)老架構(gòu)縫縫補(bǔ)補(bǔ),直到被起點(diǎn)更高的、重新設(shè)計(jì)的新架構(gòu)替代)


就如上面這幅圖,當(dāng)物理地址從傳統(tǒng)的32位向現(xiàn)代64位擴(kuò)展以后,有些尷尬了:
1、傳統(tǒng)的pcie的地址空間卡在了高位(地址>32位)內(nèi)存空間和低位內(nèi)存空間之間。
2、高位(地址>32位)內(nèi)存空間又卡在了高位的pci的地址空間(基本都是GPU計(jì)算)和傳統(tǒng)的pci地址空間之間。
對(duì)于恨不得天天進(jìn)行碎片整理、有技術(shù)強(qiáng)迫癥的人,上面這幅圖實(shí)在令人淚奔。
然后,整個(gè)物理地址的各個(gè)部分(內(nèi)存部分,pci(e)部分,bios部分等等)的起始、結(jié)束地址,又被寫(xiě)回到CPU里的 addr region寄存器組里,這些addr region寄存器組所記錄的關(guān)鍵的起始、結(jié)束地址,組成了CPU物理地址decoder所依據(jù)的數(shù)據(jù)結(jié)構(gòu)字典。


二、從起點(diǎn):intel x86 CPU架構(gòu),向下走:從物理地址到某一類(lèi)硬件模塊




我們跟隨著CPU的邏輯,拿著物理地址,去找尋對(duì)應(yīng)的硬件:

1、若是物理地址指向了內(nèi)存
該物理地址是代表了物理內(nèi)存還是PCIE卡?
——喔,根據(jù)addr region寄存器組,decoder判斷這個(gè)物理地址是內(nèi)存的地址空間。

該地址在哪個(gè)硬件上?
——喔,根據(jù)SAD/TAD解析規(guī)則 + 內(nèi)存interleaving規(guī)則 + UMA/NUMA算法規(guī)則,物理地址落到了CPU 某個(gè) IMC(內(nèi)存控制器)的某個(gè)channel,然后落到per-channel地址。

迄今為止,筆者也只能將物理地址手?jǐn)]到 內(nèi)存channel編號(hào)(也就是能將物理地址所代表的故障定位到一個(gè)channel)。而接下來(lái)解析per-channel地址,乃至rank地址,內(nèi)存column/raw地址,這是專(zhuān)業(yè)內(nèi)存領(lǐng)域的范疇了,我還沒(méi)有走到。
(此處可以單寫(xiě)一個(gè)專(zhuān)題:物理地址到物理內(nèi)存的映射解析)
網(wǎng)上有類(lèi)似的文章:

publ_2017_hillenbrand_xeon_decodingfor system addr.bdf,
倆老外拿著一臺(tái)服務(wù)器哼哧哼哧的換內(nèi)存條以及dump,硬把Intel上一代grantley 平臺(tái)的物理地址映射到內(nèi)存條的算法和數(shù)據(jù)結(jié)構(gòu)給反向分析出來(lái)了,niubility!?。?!
呃,我也同樣傻過(guò),我也讀過(guò)skylake CPU的addr region寄存器里的數(shù)據(jù)結(jié)構(gòu):缺省情況下,內(nèi)存物理地址在硬件間的interleave粒度是256B......數(shù)據(jù)太多就不啰嗦了。

我們回頭返回到起點(diǎn)吧。

2、若是物理地址指向了PCI
該物理地址是代表了物理內(nèi)存還是PCIE卡?
——喔,根據(jù)addr region寄存器組,decoder判斷這個(gè)物理地址是PCI的地址空間。
該地址在哪個(gè)硬件上?
——喔,根據(jù)mmcfg 找到對(duì)應(yīng)的pci的 bus地址:bus:dev:fun格式的地址和 mmio空間。這個(gè)bus地址才是pci設(shè)備真正的位置標(biāo)識(shí)啊。(其實(shí)有些pci還有另外一種地址,叫ioport地址。這個(gè)ioport地址不屬于物理地址的范疇,是屬于另外一個(gè)空間,這里不多說(shuō)了)
對(duì)pcie mmio空間的訪問(wèn),即是對(duì)PCIE設(shè)備的訪問(wèn)。同時(shí)CPU的IOMMU 模塊又會(huì)將mmio空間 和所分配的物理內(nèi)存buffer連接起來(lái)形成dmar表,為DMA功能服務(wù)。
(此處可以單寫(xiě)兩個(gè)專(zhuān)題:1、物理地址到PCI設(shè)備的映射解析2、PCI三大地址空間)


我們回頭返回到起點(diǎn)吧。



三、從起點(diǎn):x86硬件架構(gòu),向上走:從物理地址到操作系統(tǒng)


物理地址是硬件資源可訪問(wèn)空間的系統(tǒng)編址,所以物理地址直接代表著硬件資源,Intel文檔中將物理地址又稱(chēng)為系統(tǒng)地址。
在以前的技術(shù)貼中,我曾經(jīng)將bios比作開(kāi)天辟地的盤(pán)古大神。當(dāng)bios完成所有的硬件編排工作以后,就藏到角落里修仙去了,而操作系統(tǒng)接過(guò)管理的指揮棒。
到了操作系統(tǒng)的領(lǐng)域,物理地址又叫實(shí)地址。
操作系統(tǒng)在引導(dǎo)的初始階段,基本內(nèi)核會(huì)使用物理地址來(lái)進(jìn)行boot和引導(dǎo)(那時(shí)的世界還很簡(jiǎn)單),此時(shí)又叫實(shí)模式。
等到了操作系統(tǒng)啟動(dòng)下一階段,就開(kāi)始使用另外一套地址空間了——也就是虛擬地址所代表的虛擬空間,此時(shí)就叫保護(hù)模式(世界開(kāi)始變得復(fù)雜了)。
也許是因?yàn)橘Y源實(shí)在有限,總也滿足不了軟件的需求吧,或許是因?yàn)檐浖偸怯泻糜袎模瑝牡募一飼?huì)威脅到整個(gè)系統(tǒng)。所以當(dāng)操作系統(tǒng)完全啟動(dòng)以后,我們能看到的操作系統(tǒng)部分,以及之上的軟件都使用另外一套地址體系:虛擬地址,不再和硬件資源發(fā)生直接聯(lián)系了。
以Linux為例,每個(gè)軟件執(zhí)行個(gè)體:線程,它的運(yùn)行分為用戶態(tài)和內(nèi)核態(tài)。
用戶態(tài)就是指線程在自己的用戶地址空間里執(zhí)行著自己的運(yùn)算代碼。

(喔,這里可以再寫(xiě)一個(gè)專(zhuān)題:linux進(jìn)程空間分布)


而內(nèi)核態(tài)就是指線程通過(guò)系統(tǒng)調(diào)用申請(qǐng)了硬件資源,這個(gè)申請(qǐng)?jiān)诓僮飨到y(tǒng)內(nèi)核的處理過(guò)程。
而無(wú)論用戶態(tài)還是內(nèi)核態(tài),我們通過(guò)工具所抓取到的地址都是用虛擬地址標(biāo)識(shí)的。


例如我們用C語(yǔ)言寫(xiě)了一個(gè)程序,printf一個(gè)合法的用戶空間的指針變量,打印出來(lái)的地址,是用戶空間的虛擬地址。



又例如我們通過(guò)探針或者dump分析看到的內(nèi)核中的ffffffff8110cb3d這樣的形式,這是內(nèi)核空間的虛擬地址。


當(dāng)然上圖表示的是內(nèi)核代碼段的地址,而內(nèi)核的數(shù)據(jù)段又是另一個(gè)地址段了。

用戶空間的虛擬地址更“虛”,甚至有些虛擬地址還對(duì)應(yīng)不到物理地址上(以?xún)?nèi)存硬件資源為例)。就以?xún)?nèi)存為例,這就是Linux系統(tǒng)所謂的內(nèi)存空間懶分配原則:
按照線程的指令需求,系統(tǒng)分配器給線程分配了一段虛擬地址空間(例如語(yǔ)句定義了一個(gè)數(shù)組);
但這段虛擬地址空間不會(huì)立刻映射到物理地址(內(nèi)存)上,此時(shí)也就沒(méi)占用內(nèi)存物理資源;
直到這段虛擬地址空間需要寫(xiě)入數(shù)據(jù)的時(shí)候(例如數(shù)組賦值),系統(tǒng)才真正分配、對(duì)應(yīng)到物理地址所代表的內(nèi)存空間上。
這種懶分配的方式,放到存儲(chǔ)上或者云系統(tǒng)上,很像所謂的thin provision。
(這里可以再寫(xiě)一個(gè)專(zhuān)題:linux空間分配、缺頁(yè)中斷以及page映射機(jī)制)

若是虛擬地址已經(jīng)映射到了以page為單位物理地址,那么從虛擬地址到物理地址的翻譯,卻需要從虛擬地址開(kāi)始,通過(guò)內(nèi)存中的pdt表,進(jìn)行一級(jí)二級(jí)三級(jí)四級(jí)五級(jí)等多級(jí)映射,才能獲得物理地址。所以有些文檔,將用戶空間的虛擬地址稱(chēng)為線性地址。



(這里可以再寫(xiě)一個(gè)專(zhuān)題:線性地址到實(shí)地址的轉(zhuǎn)換。)

而內(nèi)核空間的虛擬地址相對(duì)“”實(shí)”一些,內(nèi)核虛擬地址減掉一個(gè)固定的offset偏移量,一步到位就得到了物理地址。所以有些文檔將內(nèi)核虛擬地址稱(chēng)為段偏移地址或者稱(chēng)為直接映射地址。



(這里可以再寫(xiě)一個(gè)專(zhuān)題:linux 32位和64位系統(tǒng)空間詳解)
那么到底是誰(shuí)會(huì)負(fù)責(zé)操作上文說(shuō)的“虛擬地址到物理地址的翻譯”?
答案是:CPU內(nèi)部的MMU module。
于是,順著來(lái)時(shí)的路向前走,我們沒(méi)有回頭,從高層面的操作系統(tǒng)和軟件繼續(xù)向前走,沿著代碼執(zhí)行的這條路,卻回到了硬件最底層的CPU。



輪回啊……

四、從操作系統(tǒng)回到CPU,聊聊MMU和三級(jí)cache。

整個(gè)的路程畫(huà)了個(gè)大圈圈。



Skylake CPU內(nèi)有三級(jí)緩存。L1 又叫FLC,分為DCU,ICU;L2又叫MLC;L3又叫LLC.
CPU core在load和執(zhí)行新程序語(yǔ)句的時(shí)候,靠近處理核心的L1 cache里面,獲取的地址變量(語(yǔ)句帶的)都是虛擬地址。
當(dāng)CPU core需要對(duì)該地址進(jìn)行尋址、做數(shù)據(jù)操作的時(shí)候:
首先要通過(guò)MMU實(shí)現(xiàn)虛擬地址到物理地址的翻譯;
再通過(guò)addr decoder進(jìn)行物理地址到硬件的尋址。



為了加速以上虛擬地址到物理地址翻譯的過(guò)程, CPU里出現(xiàn)了TLB緩存:將曾經(jīng)用過(guò)的地址翻譯條目放在這個(gè)緩存中?!覀兙陀锌赡苤苯油ㄟ^(guò)虛擬地址拿到物理地址,就不用再多級(jí)映射翻譯了。
為了加速數(shù)據(jù)讀取/寫(xiě)入的速度,CPU里設(shè)計(jì)了三級(jí)cache?!覀兙筒挥妹看味荚L問(wèn)主存來(lái)獲取數(shù)據(jù)了,以前曾訪問(wèn)過(guò)的熱數(shù)據(jù)直接就從CPUcache中獲取了。



看看下圖CPU cache與主存的訪問(wèn)延遲對(duì)比吧



(這里又可以寫(xiě)兩個(gè)專(zhuān)題:CPU cache實(shí)現(xiàn)和MMU工作原理。)

所以這一路走來(lái),就是個(gè)輪回,從x86架構(gòu)到操作系統(tǒng),又從操作系統(tǒng)的指令執(zhí)行回到了CPU,畫(huà)了一個(gè)圈又回到了起點(diǎn)。


五、寫(xiě)在本篇最后
本篇所有技術(shù)內(nèi)容,都是自學(xué)總結(jié)的。自學(xué)啊自學(xué),龜速又很可能發(fā)生錯(cuò)誤。

玩了兩年年的x86,潛心看了看Intel CPU架構(gòu)和linux內(nèi)核。最終形成了本篇世界觀。

我的世界觀,畢竟是自己的理解和總結(jié),錯(cuò)誤總會(huì)有,但至少我努力的從世界是什么樣的角度思考著世界為什么這樣。

本文中所有經(jīng)過(guò)的地方,其實(shí)都是這兩年踩過(guò)的技術(shù)點(diǎn)。為了盡快的形成一個(gè)知識(shí)小體系,好多地方踩的不深,留下了許多沒(méi)填坑。
寫(xiě)下此篇技術(shù)總結(jié),也算整理了這兩年的技術(shù)體系總綱。數(shù)了數(shù)有多少坑,好像這一路坑不少,未來(lái)努力,填完。
最近在看Gregg的走向性能之巔性能調(diào)優(yōu)的書(shū),發(fā)現(xiàn)dtrace工具似乎和centos兼容性不太好,又得將書(shū)中dtrace語(yǔ)句翻譯成systemtap語(yǔ)句,又是個(gè)超級(jí)大坑。

本文圖片借用了幾張 the truman show的海報(bào),懷念當(dāng)年,懵懂的看著世界是什么樣的青春。


另外,更多未更新的知識(shí)內(nèi)容,請(qǐng)關(guān)注公眾號(hào):雪瀑牽裳的樹(shù)屋,那里有intel x86 cpu架構(gòu),有l(wèi)inux內(nèi)核,還會(huì)有openstack,openshift等云計(jì)算方面的內(nèi)容。


編輯于 2020-05-31 17:17

「真誠(chéng)贊賞,手留余香」

贊賞

還沒(méi)有人贊賞,快來(lái)當(dāng)?shù)谝粋€(gè)贊賞的人吧!

x86


CPU 指令集


ARM 架構(gòu)


發(fā)布一條帶圖評(píng)論吧


5 條評(píng)論

默認(rèn)

最新

花滿樓

"呃,我也同樣傻過(guò),我也讀過(guò)skylake CPU的addr region寄存器里的數(shù)據(jù)結(jié)構(gòu):缺省情況下,內(nèi)存物理地址在硬件間的interleave粒度是256B......數(shù)據(jù)太多就不啰嗦了。"-----這個(gè)有解析過(guò)程嗎,求文檔

2022-06-28

回復(fù)喜歡

L-indica

講的好棒啊

2021-10-29

回復(fù)喜歡

Mr.Z

寫(xiě)得好棒?。?/p>

2021-04-29

回復(fù)喜歡

仕明

同時(shí)CPU的IOMMU 模塊又會(huì)將mmio空間…
//這里應(yīng)該是筆誤吧,iommu是屬于pci設(shè)備的

2021-01-29

回復(fù)喜歡

ZZ ZZ

講得真好

2020-09-25



【知乎】x86架構(gòu)&linux內(nèi)核系列(五-六)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
历史| 内丘县| 临朐县| 林芝县| 商南县| 商都县| 怀柔区| 苗栗县| 广河县| 九龙县| 凌云县| 柳林县| 合水县| 曲沃县| 延川县| 英德市| 通州市| 婺源县| 东明县| 正镶白旗| 安远县| 梁山县| 安新县| 江源县| 岐山县| 武平县| 克山县| 盐山县| 江陵县| 石林| 阳谷县| 阿克陶县| 天等县| 长宁县| 九台市| 陆河县| 乌苏市| 黄浦区| 丰原市| 依兰县| 错那县|