2013-01-22 61 views
7

編譯Linux內核2.6.34.3對ARMv7(Cortex-A8的)Linux內核ARM轉換表基(TTB0和TTB1)

我看着內核代碼,它看起來像Linux內核設置了硬件頁表TTB1(轉換表基礎)上的內核地址空間(超過0xC0000000的所有內容)和ttb0上的所有用戶進程(0xC0000000以下的所有內容),每個進程上下文切換都會發生更改。它是否正確?我仍然困惑MMU如何知道翻譯需要哪些ttb?

我讀到TTBCR(轉換表基本控制寄存器)確定哪個ttb寄存器在找不到MVA時行走,但是寄存器始終讀爲0,這意味着始終使用ARM體系結構參考手冊中的TTBR0。這怎麼可能?任何人都可以向我解釋Linux內核如何使用這兩個ttbs?

我讀了如何從這個網站http://www.cs.rutgers.edu/~pxk/416/notes/09a-paging.html入藏作品,但我還是不明白內核如何使用這兩種TTBS

(雙重檢查內核代碼,因爲某些原因都ttb0和ttb1設置,但似乎像ttb1從來沒有使用過,我把TTB1寄存器設置爲0,並且Linux內核像往常一樣繼續運行)

+1

在你包圍的鏈接,'TTBR0仍將包含操作系統的內存映射和內存映射I/O.',我猜他們的意思是說'TTBR1仍將包含操作系統的內存映射,內存映射I/O.',這對3G/1G(2G/2G)內存拆分更有意義。 'TTBR0'映射進程AS,地址從0到0xbfffffff,'TTBR0'在每個進程切換期間切換。 'TTBR1'永遠不會被修改,因爲它包含了到內核AS的鏈接(從具有3G/1G分裂的Linux上的0xc000000開始)。 – Benoit

+0

感謝您的回覆,所以對於每個表格散步,硬件只使用TTB0是否正確?硬件不使用TTBCR來確定哪些ttb寄存器要走?那麼TTB1僅用於將OS頁面複製到進程頁面? – MrGigu

回答

13

TTBR寄存器一起用於確定完整的32位或40位地址空間的尋址。哪個寄存器用於通過TTBCR中的tXsz位控制哪些地址範圍。對於TTBR0有一個t0sz,對於TTBR1有一個t1sz。

由每個TTBRx寄存器尋址的頁表是獨立的,但通常情況下,大多數Linux實現只使用TTBR0。 Linux期望能夠使用ARM不支持的3G/1G地址空間分區方案。如果您查看ARMv7體系結構參考手冊的B3-1345頁,您會看到t0sz和t1sz的值分別決定了TTBR0和TTBR1支持的地址範圍。爲了增加混淆迷茫,TTBR0和TTBR1支持非連續範圍的地址空間甚至可能會分離,導致系統地址空間出現漏洞。美好時光!

爲了回答你的主要問題,ARM推薦TTBR0用於存儲USER進程使用的頁表的偏移量,TTBR1用於存儲KERNEL使用的頁表的偏移量。我還沒有看到實際執行此操作的單個實現。在所有情況下幾乎都使用TTBR0,TTBR1包含L1表的副本。

那麼這是如何工作的? TTBR的值作爲過程狀態的一部分存儲,並在每次切換過程時進行簡單恢復。這是預期的工作方式。最初,TTBR1會爲內核表保存一個常量值,並且永遠不會被替換或換出,而TTBR0會在每次在進程之間進行上下文切換時更改。顯然ARM的大多數Linux實現都決定基本上不使用TTBR1,並堅持使用TTBR0來處理所有事情。

如果您想在設備上測試此理論,請嘗試重擊TTBR1並觀察沒有發生任何事情。然後嘗試重擊TTBR0並觀察系統崩潰。我還沒有遇到過一次沒有導致完全相同結果的實例。長話短說,TTBR1對於Linux來說毫無用處,TTBR0幾乎完全被使用並且簡單地換出來。

現在,一旦你獲得了LPAE的支持,把所有這些扔掉並重新開始。這是一個實現,你將開始看到t0sz和t1sz的值不是零,因此N也是。

+0

作爲額外的信息,請查看此鏈接。 http://linuxkernelarticles.blogspot.com/2013/03/updating-ttbr-in-arm-during-context.html – Eeyore

+0

不是T0SZ = 0和T1SZ = 2中得到的3G/1G地址空間分割? –

1

我對ARM體系結構知之甚少,但從我在封閉鏈接中讀到的內容中,以這種方式實現其虛擬內存管理:

虛擬地址的高位決定使用哪一個。取決於虛擬地址的最高n位是0(使用TTBR0)還是不使用(使用TTBR1),表的基址存儲在兩個基址寄存器(TTBR0或TTBR1)之一中。 n的值由轉換表基地控制寄存器(TTBCR)定義。

寄存器TTBCR告訴其中涉及從頁表由TTBR0TTBR1指出,將被翻譯。如果TTBCR包含0xc000000,則從00xbfffffff的任何地址都由TTBR0指向的頁錶轉換,並且0xc00000000xffffffff的任何地址都由TTBR1指向的頁錶轉換。這與用於內核的用戶進程/ 1GB的Linux內存分割相匹配。

這允許我們設計一個操作系統和內存映射I/O位於地址空間的上部並由TTBR1中的頁表管理並且用戶進程位於地址空間的下部的內存並由TTB0中的頁表管理。在上下文切換時,操作系統必須將TTBR0更改爲指向新進程的第一級表。 TTBR1仍將包含操作系統和內存映射I/O的內存映射。

因此,TTBR1的值永遠不會改變,因爲您希望內核被永久映射(想想發生中斷時會發生什麼)。另一方面,TTBR0在每個進程切換器都被修改,它包含當前進程的頁表。

+1

「如果位[31:32-N]將虛擬地址的都是0時,使用轉換表基址寄存器0否則使用翻譯表基址寄存器1」沒有N值,可以分離內核地址(> = 0xC0000000的)和。用戶地址(<0xC0000000的比方說N是最小值1,則最大的虛擬地址是0x7FFFFFFF的,這意味着較小的地址使用TTB0和一切較大將使用TTB1它不可能設置一個N值滿足3GB:1GB用戶/內核地址分割(2:2工程雖然) – MrGigu

+0

您的描述TTBCR是如何被用來確定TTBR0或TTBR1是否適用不正確MrGigu的評論是正確的TTBR0可用的最大虛擬地址(當也使用TTBR1 )是爲0x7FFFFFFF。 –

1

參見http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/Bihgfcgf.html

對於ARM5和降低TTB表被固定在尺寸和對齊(至16k)。每個1級條目代表1MB。表條目是32位(16k * 1M /(32bit/8)= 4GB)。該TTBCR控件TTBR0表大小。從上面的URL,其用於翻譯表基址寄存器

選擇
翻譯表基址寄存器被選擇如下:
如果N = 0,總是使用翻譯表基址寄存器0
- 這是重置時的默認情況。它與ARMv5或更早版本的處理器向後兼容。
如果N大於0,則:
- 如果位[31:32-N]將虛擬地址的都是0時,使用轉換表基址寄存器0否則使用翻譯表基址寄存器1.

所以TTBR0的大小也設置了內存拆分。對於 傳統的 Linux 3G/1G 1G/3G,應該選擇值。 4kB表== 1G內存==位31..30爲零。對於值該表是256byte == 64MB ==位31..26是零。

在Linux的說法,這些都是頁全球項(這將這座頁全球目錄)。條目可以指向另一個表,或者只是1MB 。接下來的表條目是頁中間 Linux目錄然後最後頁表條目。我認爲頁中間的條目在ARM上未使用。

MMU硬件不會每次都走這些表。有一個TLB(翻譯旁觀緩衝區)。它就像MMU表的緩存。當操作系統更新這些表時,TLB必須刷新或者處理器將使用陳舊的條目。類似地,ARM高速緩存是虛擬標記爲的,因此更改映射也可能意味着必須刷新高速緩存。由於這些原因,你永遠不會想要改變上下文切換的東西。共享庫文本(例如libc.so)應該在上下文切換上相同。希望每個進程都將libc.so映射到相同的虛擬地址。這樣做有很大的收穫;較低的內存使用和良好的I-cache使用。

PID寄存器以及管理員/用戶模式也可以控制存儲器訪問。這些是可以在上下文切換上切換的單個寄存器。

有關ARMV5上的PID和域使用信息,請參見http://lwn.net/images/conf/rtlws11/papers/proc/p01.pdf。目前的Linux源代碼並不完全像紙介紹的那樣。 Linux完全有可能不需要使用此機制,並將TTBCR設置爲零,以便ARM子體系結構的VM代碼相似。

編輯:相信TTBCR功能可用於實現3G/1G分裂。我認爲Rutger的頁面一般在討論TTBCR,而不是在Linux上下文中。此外,至少所述2.6.38 Linux中使用DACR但因爲它支持的處理有限數量的不使用PIDFCSE

http://lwn.net/Articles/106177/ - 也引用羅格斯頁。

+0

有趣的論文,但是使用FCSE的每個進程限制爲32MB,我不認爲一個正常的Linux發行版將強制用戶,但是對於受限的嵌入式設備看起來可行。 – MrGigu

+0

Im平靜混淆,將N位設置爲2,如果指所有虛擬地址<= 0x3FFF FFFF將使用TTB0和更大的使用TTB1。這是一個3GB:1GB的用戶/內核拆分? – MrGigu

+0

拆分爲1G/3G(根據編輯),並且該功能很可能未被Linux使用。此外,* fcse *在較新的ARM CPU上不推薦使用。 –