1. 程式人生 > >(轉)CPU地址空間小結

(轉)CPU地址空間小結

地址空間的對映

這裡要說的是Intel構架下的CPU地址空間佈局,注意這裡沒有說是記憶體地址空間佈局。

       我們說的記憶體通常是指DRAM,DRAM相對於CPU也可以算是外部裝置,CPU地址空間是CPU訪問外部裝置過程中的一個概念,CPU除了訪問DRAM外還會訪問許多其他的裝置。可以粗略的認為CPU地址空間包含DRAM地址空間,但兩者卻是不同的概念。而且DRAM地址空間是由記憶體控制器直接訪問的,由CPU間接訪問的

過去很長一段時間Intel CPU是32位的,也就是可以訪問到4GB的地址空間,但是當時的DRAM通常也就是512MB到2GB之間,現在假設DRAM是1GB,那麼就是3GB的地址空間是空的。在計算機裡面,地址也是資源。這空的地址空間就用來訪問外部裝置IO所用,這部分被稱為MMIO(Memory Mapped I/O)。MMIO的空間是很大的,它包含了PCI的配置空間(256MB或者更大),內建整合視訊記憶體(256MB,或者更大),還有其他很多東西 。所以這部分的大小是不容忽視的。


       現在的Intel CPU一般都是36位的,也就是可以訪問到64GB。而DRAM也是越來越大,以至於DRAM加上MMIO的空間超出了4GB,而MMIO的空間是不能隨意變更的。所以現在的做法就是將DRAM的一部分重對映到4GB以上的空間,下面就以DRAM有5GB為情況,做一個例子。請看下圖


上圖中左邊是地址空間,右邊是DRAM空間,其中紅色的字體表示暫存器,可以在spec中找到該暫存器的說明,這幾個暫存器決定了整個地址空間的大的格局。這裡就簡要說明一下。

      TOLUD,指向32位地址,也就是4GB以內。它是一個分界線,在0-TOLUD之間為DRAM,TOLUD-4GB之間為MMIO空間。該值由BIOS指定。為了方便說明,假設TOLUD被指定為2GB。

      TOM,目前還不明確,我猜想應該是指實際實體記憶體的大小,“the total amount of populated physical
memory”,比如上圖TOM為5GB。可在本機的BDFR(0,0,0,A0)驗證。

      REMAPBASEREMAPLIMIT,也是36位,分別表示基址和上限地址。用於重對映DRAM中被MMIO遮住的一部分空間,有2GB。該圖中將DRAM中遮住的部分重對映到TOM的上方,所以REMAPBASE為5GB,REMAPLIMIT為7GB-1。

      TOUUD,36位地址,大小為REMAPLIMIT+1的位置,比如上圖TOUUD應該在7GB的位置,可以和TOLUD做對比理解,TOLUD是4GB以內DRAM與MMIO的分界線,TOUUD可以理解為4GB-64GB之間DRAM與MMIO的分界線。


      以上是假設DRAM超出4GB的情況,假如DRAM只有3GB,而TOLUD指定為2GB呢?也就是2GB-3GB的DRAM被遮住。這時也是通過REMAPBASE和REMAPLIMIT將之重定向到4GB的上方。再假設DRAM只有2GB,TOLUD為2GB呢?這時就不存在重對映。 REMAPLIMIT小於REMAPBASE時(通常REMAPLIMIT為0),表示不使用重對映。

1.實體記憶體,在不引起誤解的情況下,是指非專業人士、專業人士都懂的——記憶體條,比如SDRAM、DDR/DDR2/DDR3/DDR4/DDR5等記憶體條。 

2.虛擬地址(如果存在的話,見後面4)是程式設計師視角的地址,比如C語言中的指標值,彙編程式設計師使用CPU指令產生的定址。

3.實體地址是CPU晶片地址引腳(假定記憶體控制器沒有整合在CPU中)發出的訪存地址,實體地址還要被記憶體控制機構(一般在北橋晶片中)進行譯碼或對映(對映的一個例子見本文最後17部分提到的“實體記憶體回收”),可能實際指向DRAM(就是前面提到的記憶體條),也可能通過一些外部匯流排(比如PCI)指向各種外部裝置。對外部裝置的這種訪問一般也稱為MMIO:Memory Mapped I/O——記憶體對映I/O。另外特別提一下,x86支援用I/O指令(IN、OUT)定址的另外的獨立64K I/O地址空間,該地址空間不要和這裡實體記憶體地址混淆。

4. 綜合前面:邏輯地址(經段轉換到)-->線性地址(如果分頁使能就是虛擬地址,此時虛擬地址經分頁對映到)-->實體地址(經譯碼轉換到)-->記憶體條上的實體記憶體地址或MMIO地址。

一般來說,在系統執行時,外設的I/O記憶體資源的實體地址是已知的(通過request_mem_region()),由硬體的設計決定。但是CPU通常並沒有為這些已知的外設I/O記憶體資源的實體地址 預定義虛擬地址範圍,驅動程式並不能直接通過實體地址訪問I/O記憶體資源,而必須將它們對映到核心虛地址空間內(通過頁表),然後才能根據對映所得到的核 心虛地址範圍,通過訪內指令訪問這些I/O記憶體資源。Linux在io.h標頭檔案中聲明瞭函式ioremap(),(在核心驅動程式的初始化階段,通過ioremap()將實體地址對映到核心虛擬空間(3GB-4GB);在驅動程式的mmap系統呼叫中,使用remap_page_range()將該塊ROM對映到使用者虛擬空間。這樣核心空間和使用者空間都能訪問這段被對映後的虛擬地址。)