一、前言 作為一個多年耕耘在linux 2.6.23內(nèi)核的開發(fā)者,各個不同項目中各種不同周邊外設驅(qū)動的開發(fā)以及各種瑣碎的、扯皮的俗務占據(jù)了大部分的時間。當有機會下載3.14的內(nèi)核并準備學習的時候,突然發(fā)現(xiàn)linux kernel對于我似乎變得非常的陌生了,各種新的機制,各種framework、各種新的概念讓我感到閱讀內(nèi)核代碼變得舉步維艱。 還好,剖析內(nèi)核的熱情還在,剩下的就交給時間的。首先進入視線的是Device Tree機制,這是和porting內(nèi)核非常相關(guān)的機制,如果想讓將我們的硬件平臺遷移到高版本的內(nèi)核上,Device Tree是一個必須要掃清的障礙。 我想從下面三個方面來了解Device Tree: 1、為何要引入Device Tree,這個機制是用來解決什么問題的?(這是本文的主題) 2、Device Tree的基礎概念(請參考DT基礎概念) 3、ARM linux中和Device Tree相關(guān)的代碼分析(請參考DT代碼分析) 閱讀linux內(nèi)核代碼就像欣賞冰山,有看得到的美景(各種內(nèi)核機制及其代碼),也有埋在水面之下看不到的基礎(機制背后的源由和目的)。沉醉于各種內(nèi)核機制的代碼固然有無限樂趣,但更重要的是注入更多的思考,思考其背后的機理,真正理解軟件抽象。這樣才能舉一反三,并應用在具體的工作和生活中。 本文主要從下面幾個方面闡述為何ARM linux會引入Device Tree: 1、沒有Device Tree的ARM linux是如何運轉(zhuǎn)的? 2、混亂的ARM architecture代碼和存在的問題 3、新內(nèi)核的解決之道
二、沒有Device Tree的ARM linux是如何運轉(zhuǎn)的? 我曾經(jīng)porting內(nèi)核到兩個ARM-based的平臺上。一個是小的芯片公司的應用處理器,公司自己購買了CPU core,該CPU core使用ARM兼容的指令集(但不是ARM)加上各種公司自行設計的多媒體外設整合成公司的產(chǎn)品進行銷售。而我的任務就是porting 2.4.18內(nèi)核到該平臺上。在黑白屏幕的手機時代,那顆AP(application process)支持了彩屏、camera、JPEG硬件加速、2D/3D加速、MMC/SD卡、各種音頻加速(內(nèi)置DSP)等等特性,功能強大到無法直視。另外一次移植經(jīng)歷是讓2.6.23內(nèi)核跑在一個大公司的冷門BP(baseband processor)上。具體porting的方法是很簡單的: 1、自己撰寫一個bootloader并傳遞適當?shù)膮?shù)給kernel。除了傳統(tǒng)的command line以及tag list之類的,最重要的是申請一個machine type,當拿到屬于自己項目的machine type ID的時候,當時心情雀躍,似乎自己已經(jīng)是開源社區(qū)的一份子了(其實當時是有意愿,或者說有目標是想將大家的代碼并入到linux kernel main line的)。 2、在內(nèi)核的arch/arm目錄下建立mach-xxx目錄,這個目錄下,放入該SOC的相關(guān)代碼,例如中斷controller的代碼,時間相關(guān)的代碼,內(nèi)存映射,睡眠相關(guān)的代碼等等。此外,最重要的是建立一個board specific文件,定義一個machine的宏:
在xxx_init函數(shù)中,一般會加入很多的platform device。因此,伴隨這個board specific文件中是大量的靜態(tài)table,描述了各種硬件設備信息。 3、調(diào)通了system level的driver(timer,中斷處理,clock等)以及串口terminal之后,linux kernel基本是可以起來了,后續(xù)各種driver不斷的添加,直到系統(tǒng)軟件支持所有的硬件。 綜上所述,在linux kernel中支持一個SOC平臺其實是非常簡單的,讓linux kernel在一個特定的平臺上“跑”起來也是非常簡單的,問題的重點是如何優(yōu)雅的”跑”。
三、混亂的ARM architecture代碼和存在的問題 每次正式的linux kernel release之后都會有兩周的merge window,在這個窗口期間,kernel各個部分的維護者都會提交各自的patch,將自己測試穩(wěn)定的代碼請求并入kernel main line。每到這個時候,Linus就會比較繁忙,他需要從各個內(nèi)核維護者的分支上取得最新代碼并merge到自己的kernel source tree中。Tony Lindgren,內(nèi)核OMAP development tree的維護者,發(fā)送了一個郵件給Linus,請求提交OMAP平臺代碼修改,并給出了一些細節(jié)描述: 1、簡單介紹本次改動 2、關(guān)于如何解決merge conficts。有些git mergetool就可以處理,不能處理的,給出了詳細介紹和解決方案 一切都很平常,也給出了足夠的信息,然而,正是這個pull request引發(fā)了一場針對ARM linux的內(nèi)核代碼的爭論。我相信Linus一定是對ARM相關(guān)的代碼早就不爽了,ARM的merge工作量較大倒在其次,主要是他認為ARM很多的代碼都是垃圾,代碼里面有若干愚蠢的table,而多個人在維護這個table,從而導致了沖突。因此,在處理完OMAP的pull request之后(Linus并非針對OMAP平臺,只是Tony Lindgren撞在槍口上了),他發(fā)出了怒吼: Gaah. Guys, this whole ARM thing is a f*cking pain in the ass. 負責ARM linux開發(fā)的Russell King臉上掛不住,進行了反駁:事情沒有那么嚴重,這次的merge conficts就是OMAP和IMX/MXC之間一點協(xié)調(diào)的問題,不能抹殺整個ARM linux團隊的努力。其他的各個ARM平臺維護者也加入討論:ARM平臺如何復雜,如何龐大,對于arm linux code我們已經(jīng)有一些思考,正在進行中……一時間,討論的氣氛有些尖銳,但總體是坦誠和友好的。 對于一件事情,不同層次的人有不同層次的思考。這次爭論涉及的人包括: 1、內(nèi)核維護者(CPU體系結(jié)構(gòu)無關(guān)的代碼) 2、維護ARM系統(tǒng)結(jié)構(gòu)代碼的人 3、維護ARM sub architecture的人(來自各個ARM SOC vendor) 維護ARM sub architecture的人并沒有強烈的使命感,作為公司的一員,他們最大的目標是以最快的速度支持自己公司的SOC,盡快的占領市場。這些人的軟件功力未必強,對linux kernel的理解未必深入(有些人可能很強,但是人在江湖身不由己)。在這樣的情況下,很多SOC specific的代碼都是通過copy and paste,然后稍加修改代碼就提交了。此外,各個ARM vendor的SOC family是一長串的CPU list,每個CPU多多少少有些不同,這時候#ifdef就充斥了各個源代碼中,讓ARM mach-和plat-目錄下的代碼有些不忍直視。 作為維護ARM體系結(jié)構(gòu)的人,其能力不容置疑。以Russell King為首的team很好的維護了ARM體系結(jié)構(gòu)的代碼?;旧希薽ach-和plat-目錄,其他的目錄中的代碼和目錄組織是很好的。作為ARM linux的維護者,維護一個不斷有新的SOC加入的CPU architecture code的確是一個挑戰(zhàn)。在Intel X86的架構(gòu)一統(tǒng)天下的時候,任何想正面攻擊Intel的對手都敗下陣來。想要擊倒巨人(或者說想要和巨人并存)必須另辟蹊徑。ARM的策略有兩個,一個是focus在嵌入式應用上,也就意味著要求低功耗,同時也避免了和Intel的正面對抗。另外一個就是博采眾家之長,采用license IP的方式,讓更多的廠商加入ARM建立的生態(tài)系統(tǒng)。毫無疑問,ARM公司是成功的,但是這種模式也給ARM linux的維護者帶來了噩夢。越來越多的芯片廠商加入ARM陣營,越來越多的ARM platform相關(guān)的代碼被加入到內(nèi)核,不同廠商的周邊HW block設計又各不相同…… 內(nèi)核維護者是真正對操作系統(tǒng)內(nèi)核軟件有深入理解的人,他們往往能站在更高的層次上去觀察問題,發(fā)現(xiàn)問題。Linus注意到每次merge window中,ARM的代碼變化大約占整個ARCH目錄的60%,他認為這是一個很明顯的符號,意味著ARM linux的代碼可能存在問題。其實,60%這個比率的確很夸張,因為unicore32是在2.6.39 merge window中第一次全新提交,它的代碼是全新的,但是其代碼變化大約占整個ARCH目錄的9.6%(需要提及的是unicore32是一個中國芯)。有些維護ARM linux的人認為這是CPU市場占用率的體現(xiàn),不是問題,直到內(nèi)核維護者貼出實際的代碼并指出問題所在。內(nèi)核維護者當然想linux kernel支持更多的硬件平臺,但是他們更愿意為linux kernel制定更長遠的規(guī)劃。例如:對于各種繁雜的ARM平臺,用一個kernel image來支持。 經(jīng)過爭論,確定的問題如下: 1、ARM linux缺少platform(各個ARM sub architecture,或者說各個SOC)之間的協(xié)調(diào),導致arm linux的代碼有重復。值得一提的是在本次爭論之前,ARM維護者已經(jīng)進行了不少相關(guān)的工作(例如PM和clock tree)來抽象相同的功能模塊。 2、ARM linux中大量的board specific的源代碼應該踢出kernel,否則這些垃圾代碼和table會影響linux kernel的長期目標。 3、各個sub architecture的維護者直接提交給Linux并入主線的機制缺乏層次。
四、新內(nèi)核的解決之道 針對ARM linux的現(xiàn)狀,最需要解決的是人員問題,也就是如何整合ARM sub architecture(各個ARM Vendor)的資源。因此,內(nèi)核社區(qū)成立了一個ARM sub architecture的team,該team主要負責協(xié)調(diào)各個ARM廠商的代碼(not ARM core part),Russell King繼續(xù)負責ARM core part的代碼。此外,建立一個ARM platform consolidation tree。ARM sub architecture team負責review各個sub architecture維護者提交的代碼,并在ARM platform consolidation tree上維護。在下一個merge window到來的時候,將patch發(fā)送給Linus。 針對重復的代碼問題,如果不同的SOC使用了相同的IP block(例如I2C controller),那么這個driver的code要從各個arch/arm/mach-xxx中獨立出來,變成一個通用的模塊供各個SOC specific的模塊使用。移動到哪個目錄呢?對于I2C或者USB OTG而言,這些HW block的驅(qū)動當然應該移動到kernel/drivers目錄。因為,對于這些外設,可能是in-chip,也可能是off-chip的,但是對于軟件而言,它們是沒有差別的(或者說好的軟件抽象應該掩蓋底層硬件的不同)。對于那些system level的code呢?例如clock control、interrupt control。其實這些也不是ARM-specific,應該屬于linux kernel的核心代碼,應該放到linux/kernel目錄下,屬于core-Linux-kernel frameworks。當然對于ARM平臺,也需要保存一些和framework交互的code,這些code叫做ARM SoC core architecture code。OK,總結(jié)一下: 1、ARM的核心代碼仍然保存在arch/arm目錄下 2、ARM SoC core architecture code保存在arch/arm目錄下 3、ARM SOC的周邊外設模塊的驅(qū)動保存在drivers目錄下 4、ARM SOC的特定代碼在arch/arm/mach-xxx目錄下 5、ARM SOC board specific的代碼被移除,由Device Tree機制來負責傳遞硬件拓撲和硬件資源信息。 OK,終于來到了Device Tree了。本質(zhì)上,Device Tree改變了原來用hardcode方式將HW 配置信息嵌入到內(nèi)核代碼的方法,改用bootloader傳遞一個DB的形式。對于基于ARM CPU的嵌入式系統(tǒng),我們習慣于針對每一個platform進行內(nèi)核的編譯。但是隨著ARM在消費類電子上的廣泛應用(甚至桌面系統(tǒng)、服務器系統(tǒng)),我們期望ARM能夠象X86那樣用一個kernel image來支持多個platform。在這種情況下,如果我們認為kernel是一個black box,那么其輸入?yún)?shù)應該包括: 1、識別platform的信息 2、runtime的配置參數(shù) 3、設備的拓撲結(jié)構(gòu)以及特性 對于嵌入式系統(tǒng),在系統(tǒng)啟動階段,bootloader會加載內(nèi)核并將控制權(quán)轉(zhuǎn)交給內(nèi)核,此外,還需要把上述的三個參數(shù)信息傳遞給kernel,以便kernel可以有較大的靈活性。在linux kernel中,Device Tree的設計目標就是如此。 |
|
來自: jiffes > 《devicetree》