ARM與Cortex筆記-ARM MPCore (Multi-Processor Core) 多核心架構解析.

ARM與Cortex筆記-ARM MPCore (Multi-Processor Core) 多核心架構解析.


ARMCortex筆記ARM MPCore (Multi-Processor Core) 多核心架構解析.
hlchou@mail2000.com.tw
by loda
隨著目前Smart Phone的應用與複雜度增加,這類消費性電子產品,必須要能在考量功耗與持久性的前提下,達成使用者可接受的高效能,並且還要有足夠的使用與待機時間,基於如此,ARM MPCore多核心架構,就是一個在消費性電子產品上可以考慮的處理器架構選擇.
參考ARM網站有關Cortex A9 Performance的介紹(http://www.arm.com/products/processors/cortex-a/cortex-a9.php ),以雙核心架構在TSMC 40G性能優化的版本中,效能與功耗比為5.26 (DMIPS/mW),Cortex A9單一核心的Dhrystone 性能比為2.50 DMIPS/MHz,也就是說,如果希望要達到10000DMIPS,以單核心而言就需要達到2GHz的時脈,此時的總功耗約為1.9W (= 10000/5.26),但如果是以多核心的架構,就可以在時脈不需要大幅拉到2GHz的情況下,透過增加處理器數量,來達到所期待的運算DMIPS總數,而且系統功耗增加幅度也低(當然晶片的面積會增加),可以參考這份ARM的投影片“Parallel Computing in your Pocket” (參考網址:http://www.iet-cambridge.org.uk/arc/seminar07/slides/JohnGoodacre.pdf),可以看到單核心要達到三核心的效能時,透過拉高時脈達到一樣的效能時,核心的總功耗會是採用三核心方案的三倍以上,也就是說,如果作業系統上有適度的Muti-Task多工,用多核心去滿足總體效能的期待,會比單核心的架構,更符合省電的功耗效益.
在多核心的架構下,還需要去檢視作業系統的排程機制,OS Scheduling Tick是透過Interrupt Distributor發給每個處理器,則每個處理器都會透過執行排程的程式碼,選擇需要執行的Task,進行Task Context-Switch的流程,這樣的想法對於讓系統Best-Effort運作是比較合理的,但對於消費性產品而言,若可以讓系統盡可能省電,而又只會減損些微的效能,反而是種加分,
也因此,除了要確保每個處理器可以透過WFI進入省電狀態外,若是把OS Scheduling Tick固定發給Primary Processor,其它目前沒有Task執行的處理器,就進入WFI的狀態,由該Primary Processor進行排程與工作分配,non-Primary Processor接收到來自Primary ProcessorIPI中斷後,就會被喚醒,進行對應的Task Context-Switch動作,如果系統是處於不忙碌的狀態下,就會有機會讓non-Primary Processor的處理器,有機會維持比較長時間的StandBy休眠的狀態,MPCore的消費性產品,可以維持比較長時間的運作.
本文主要以ARMv7 CortexA9為主要討論的範圍(可供參考的文件例如:ARMv7-AR Architecture Reference Manual),所討論的內容,主要以筆者認為值得深入討論的項目,並不一定符合每個人對於ARM MPCore所需的範圍,最後,本文雖盡可能提供正確的資訊,若有不盡完善之處,請以ARM的文件為依歸.
多核心架構的概念
多核心的架構下,開機時,只會有一個處理器在運作稱為Primary Processor(或導引處理器BSP “bootstrap processor “),其它處理器則稱為 non-Primary Processor(或應用處理器AP “Application processor”),在系統初始化與關機過程中,都是由Primary Processor來負責,主要執行如下流程
1,Invalidate Data Cache
2,Invalidate SCU(Snoop Control Unit) duplicate tags for all processors
3,Invalidate L2 Cache
4,Enable SCU
5,Enable Data Cache
6. Enable L2 Cache
7. Set SMP mode with ACTLR.SMP.
等到作業系統初始一個段落後,才會去啟動其它的non-Primary Processor,並由這些處理器執行如下流程
1. Invalidate Data Cache
2. Enable Data Cache
3. Set SMP with ACTLR.SMP.
整個系統的排程機制就會根據這些啟動的Processor來分派工作,如果有用不到的處理器資源,也可以透過WFI(Wait For Interrupr)讓處理器處於省電的模式.
基於多處理器的架構,處理器也會提供硬體層級支援記憶體同步的指令,例如:LDREX, STREX, SWP與 SWPB,避免當有一個以上的處理器對同一個記憶體內容存取時,當該內容在處理器A中有做變動,以致使該內容在處理器B中失效時,可以透過這類指令確保處理器B可以同步到最新的內容,維持整個系統運作的正確性.
而在作業系統中SpinLock的機制,也會透過LDREX/STREX來進行,確保當作業系統進行SpinLock動作時,可以得到硬體層級的記憶體同步確保,避免SpinLock在多核心架構下的運作失誤. (透過軟體,要做到比硬體支援更有效率的自旋鎖是相對困難),
參考Linux KernelARM平台上的SpinLock實作(檔案位置arch/arm/include/asm/spinlock.h),如下所示
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
unsigned long tmp;
__asm__ __volatile__(
“1: ldrex %0, [%1]\n”
” teq %0, #0\n”
#ifdef CONFIG_CPU_32v6K
” wfene\n”
#endif
” strexeq %0, %2, [%1]\n”
” teqeq %0, #0\n”
” bne 1b”
: “=&r” (tmp)
: “r” (&lock->lock), “r” (1)
: “cc”);
smp_mb();
}
static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
unsigned long tmp;
__asm__ __volatile__(
” ldrex %0, [%1]\n”
” teq %0, #0\n”
” strexeq %0, %2, [%1]”
: “=&r” (tmp)
: “r” (&lock->lock), “r” (1)
: “cc”);
if (tmp == 0) {
smp_mb();
return 1;
} else {
return 0;
}
}
此外,
1, 處理器之間可透過IPI(Inter-Processor Interrupt)彼此溝通,
2,處理器之間是合作關係,彼此沒有從屬的關係,
3,所有的處理器都看到同樣的記憶體空間,彼此所定址的實體記憶體空間也是一樣,在同樣的記憶體位置上都是存取同樣的記憶體內容.並且,共同基於同一個作業系統程式碼,來對所有的處理器進行Task的排程工作.
4,每個處理器都是以Task為單位去進行多工,但進入到Kernel Mode (Ring0 or Supervisor Mode),所看到的記憶體內容是同一塊被保護的區間,但是切到User Mode (Ring 3 or User Mode),就是根據MMU看到各自的記憶體區塊.
5,所有的處理器都共享同樣的I/O周邊與中斷控制器,每個處理器都可以收到來自任何周邊的中斷觸發.
檢視ARM MPCore架構
ARM系列在ARM11(例如:ARM1176),就已經導入Multi-Processor Core的架構,Cortex系列,包括A5,A9A15都支援MPCore的架構,目前可以支援4個核心架構(可以參考文件: ARM11 MPCore Processor Technical Reference Manual in http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/DDI0360F_arm11_mpcore_r2p0_trm.pdf 或 Cortex-A9 MPCore Technical Reference Manual in http://infocenter.arm.com/help/topic/com.arm.doc.ddi0407e/DDI0407E_cortex_a9_mpcore_r2p0_trm.pdf ), 多核心的架構會透過Snoop Control Unit介面同步每個處理器各自的L1 Data Cache內容,並以Distributed Interrupt Controller支援既有的ARM Interrupts,每個處理器都有一個專屬的TimerWatchDog,支援Level 2 AMBA(AXI high-speed Advanced Microprocessor Bus Architecture)介面,每個處理器都有一個Integral EmbeddedICE-RT Logic用以提供JTAG除錯介面,與各自的Pipeline,Branch Prediction with Return Stack,CoProcessors 14 and 15,每個處理器都有自己的MMU (Instruction and Data Memory Management Units),主要的差異在於處理器對分頁的處理不是直接跟單核心架構一樣去操作TLB,而是每個處理器都維護自己的Micro TLB,並透過共用的Main TLB同步,每個處理器都有L1 Instruction/Data Cache,每個處理器都具備對外的32-bit Instruction Interface64-bit Data Cache,每個處理器都支援硬體的Data Cache Coherence,每個處理器都可提供Vector Floating-Point (VFP) Coprocessor 支援
ARM MPCore架構與周邊運作示意圖

Interrupt Distributor
MPCore 的架構下會透過 Interrupt Distributor 統一管理MPCore上所有處理器的中斷來源,並且依據中斷優先級分派中斷給個別的處理器.每個中斷來源,都可以設定優先級,以及當該中斷發生時,哪些處理器要收到該中斷要求.在硬體支援上,會確保一個發送給多處理器的中斷,一次只有一個處理器在處理.
Cortex A9為例,Interrupr Distributor支援224個中斷來源,每個中斷源都有唯一的ID識別(ID0-ID223),有關中斷來源分類如下所示
來源
說明
Software Generated Interrupts (SGI)可用於Inter-Processor Interrupts (IPI).每個MPCore中的處理器都會有Private Interrupt 範圍從ID0ID15,並且只能由軟體觸發中斷中斷的優先級,會由每個接收中斷的處理器自行設定決定,發出中斷的處理器無法決定接收端的優先級.
Global timer (PPI(0))透過Interrupt Distributor 使用中斷ID27
A legacy nFIQ pin (PPI(1))如果選擇Legacy FIQ mode,就會跳過Interrupt Distributor直接把中斷發給每個MPCore處理器.
反之,就會藉由Distributed Interrupt ControllerFIQ以中斷ID28發給MPCore的處理器.
Private timer, PPI(2)每個MPCore中的處理器會以中斷 ID29作為Private Timer中斷源.
Watchdog timers, PPI(3)每個MPCore中的處理器會以中斷 ID30作為Watchdog Timer中斷源.
A legacy nIRQ pin, PPI(4)如果選擇Legacy IRQ mode,就會跳過Interrupt Distributor直接把中斷發給每個MPCore處理器.
反之,就會藉由Distributed Interrupt ControllerIRQ以中斷ID31發給MPCore的處理器.
Shared Peripheral Interrupts (SPI)用以銜接周邊裝置中斷之用,可設定為Edge Sensitive (posedge) 或 Level Sensitive(high level),並從中斷編號ID32開始.(Interrupt Distributor 支援最多224個中斷源 )
Interrupt Distributor Prioritization and Selection功能,會去找出目前最高優先級的Pending中斷源(其中: 0x00為最高優先級,0x0f為最低優先級),並將該中斷透過CPU Interface進行觸發.
Interrupt Distributor 會幫每個處理器維護一個尚未處理的中斷列表,並且選擇最高優先級的中斷發給對應的處理器,若中斷優先級相同,則選擇最低的中斷源編號 (ID0-ID223) 進行觸發中斷列表中會包括:優先級,中斷觸發的目標處理器.
Interrupt Distributor 支援1-NN-N兩種中斷模式,說明如下所示
中斷模式
說明
1-N所觸發的中斷可以被任一的處理器清除,並且其他尚未處理該中斷的處理器對該中斷的狀態也會被清除.
N-N每個處理器對該中斷的處理行為各自獨立個別處理器對該中斷的清除,並不影響到其他尚未處理到該中斷處理器的中斷狀態.
當收到來自處理器發出的 ‘End of Interrupt Information (EOI)’ ,確認對應中斷在處理器已被處理完畢(Active to Inactive transition),或是通知正在進行處理(Pending to Active transition), Interrupt Distributor就會改變所維護的中斷清單狀態. MPCore處理器的中斷可以處於以下三種狀態,
Inactive: 該中斷可能尚未被觸發,或是已經觸發,並且在該處理器中被處理完畢.同時,該中斷源也可能在其他處理器中還處於Pending或是Active的狀態,會根據每個處理器處理中斷的情況而定.
Pending:該中斷已發生,但尚未在對應處理器中觸發執行.
Active:該中斷已經被執行,但尚未執行結束.
Interrupt Distributor偵測到中斷發生時,就會設定對應目標處理器該中斷的狀態為Pending.如果該中斷為Level-Sensitive,有任一MPCore處理器,對該中斷還處於Active的狀態時,則該中斷就不能設定為Pending. 如果是Edge-Sensitive,當前一個中斷尚未處理完畢,下一個中斷又發生時,MPCore,對不同處理器可能同時存在PendingActive的狀態.
Interrupt Distributor運作的概念,如下圖所示

我們可以透過Software Generated Interrupt Register 或 Interrupt Set-Pending Register 觸發軟體中斷,給特定或是一組處理器,Interrupt DistributorHardwareSoftware中斷處理的行為完全一致.只是一個來自硬體,一個是透過軟體主動觸發的軟體中斷可提供在多核心架構下,跨處理器的中斷通知機制,包括可以把一個正在WFI狀態的處理器喚醒.
MPCore每個處理器的CPU Interface 可支援中斷Priority MaskingPreempted中斷(讓高優先級的中斷可以插斷當前的中斷),一個Pending中的中斷,如果通過Priority Mask,並且優先級高於目前處理器正在執行中的Active中斷,就會被該MPCore處理器插入執行.當處理器透過Interrupt Acknowledge Register讀取目前要處理的中斷編號時,CPU Interface就會記錄該中斷的優先級,並通知Interrupt Distributor將該中斷標示為Active. 如果在處理器讀取Interrupt Acknowledge Register,該中斷因為Priority Mask更改或是透過Interrupt Pending Clear Register被取消了,則會從Interrupt Acknowledge Register讀取到1023,表示沒有需要被處理的中斷.當中斷處理完畢,就會需要處理器設定End of Interrupt Register,用以透過CPU Interface通知Interrupt Distributor將該中斷標示為Inactive.

Cache coherence機制

ARM多核心的架構下,每個處理器都會有自己的L1 Cache,並共用同一塊L2 Cache,也因為如此,當兩個處理器的Cache有暫存到同一個位址的記憶體資料時,如果沒有一個協同確認機制的就有機會導致某個處理器對同一個位址的資料做了修改,但是另一個處理器上讀出的卻是尚未修改過的內容,如此就會導致系統潛藏的錯誤問題.
ARM多核心架構下採用的是Tightly Coupled Memory,所有的處理器會共享同一塊外部記憶體,可以更自進行工作安排,由於各自的處理器有自己的L1 Cache與共享的L2 Cache,也因此,外部記憶體,L2與各處理器中的L1 Cache Coherency就會變得重要.(Loosely-coupled 各處理器就不會共享同一塊外部記憶體,各處理單元可透過Message-Passing機制進行溝通)
Cache Coherence 主要會同步每個處理器L1L2Cache,如果有處理器更新到另一個處理器Cache中也有同位址的資料內容時,就會透過這機制把有同位址資料的處理器Cache進行更新,參考有關Cache Coherence的資訊例如http://en.wikipedia.org/wiki/Cache_coherency .
ARM所採用的Snooping Control Unit主要行為為會監控個別處理器Cache 存取資料的位址,如果有一個寫入的動作發生在其他Cache也有複製到的位址的資料,Cache Controller就會把該監控的記憶體位置設定為失效. Snooping Protocol優點為,速度快,由與所有的Request/Response Transaction都會Broadcast到系統中所有單元,被所有的處理器監控到,缺點就是Snooping Protocol不適合更大型的多核新處理器架構,要不就是必須提高BusBandwidth.
其它的作法還包括Directory-Based Coherence,這是一個目錄式的架構,屬於每個Cache所共同使用到的資料會被放置在一個共通的目錄下,這個目錄工作行為就像是一個過濾器,處理器必須要透過該機制才可以把資料從外部記憶體載入到自己的Cache如果該共享的資料被改變了,目錄內容就會同步更新,或是會把相關Cache中的資料設定為失效.缺點就是,資料的取得會有比較長的延遲 (必須有 3 hop流程 Request/Respond/Forward),好處是Transaction過程,只需要跟Directory-based Controller同步就好,不需要對系統中所有的單元Broadcast. 一般來說,超過64個處理器單元的架構,就會採用Directory-based.
Snoop Control Unit
SCU 主要用以連結1-4MPCore處理器,透過AXI Bus去存取Memory system,主要功能包括
1,同步每個MPCore處理器的Data Cache內容 (不包括Instruction Cache的同步)
2,初始化L2 CacheAXI Memory Access的行為
3,仲裁每個MPCore處理器對L2 Cache的存取行為
4,管理ACP(Accelerator Coherency Port)介面的存取
ACP(Accelerator Coherency Port)主要用於連接原本不被處理器Cache管理的AXI Master週邊,例如:DMA Engine. 過往的設計中,如果有一塊記憶體是會被硬體DMA直接更動內容,則該記憶體我們就會設定為non-Cached,以避免因為處理器的Cache把該記憶體內容暫存,但該記憶體內容在外部記憶體中卻已經被硬體修改了,導致兩者不一致的執行正確性問題為了規避這問題,選擇把對應記憶體的Cache關閉,帶來的缺點就是處理器必須去等待外部相對Cache而言較慢速的記憶體進行資料的存取,導致效能上的減損也因此,透過SCU上的ACP,就可以讓硬體DMA更動資料內容時與處理器內部的Cache保持一致性,就算硬體DMA要更動對應記憶體位址的內容,基於ACP的同步機制,就可以在開啟處理器Cache的狀態下,確保Cache內容被更新到,讓整體運作效能維持在高檔.
ACP主要目的為讓其它裝置也可以共享並存取L1/L2 Cache中的資料內容,以期可以在不增加系統功耗的情況下(減少到外部記憶體存取的次數)增加系統效能. ACP裝置Read/Write的行為如下所示
READACP上的裝置,要進行Read動作時,會先確認資料是否有在L1 Cahce,反之,則確認是否有在L2 Cache,最後才是從外部記憶體中取得,也就是說如果資料有在L1或是L2 Cache,ACP上的裝置會直接從Cache中抓取資料,加速運作的效率
WRITEACP上的裝置,要進行Write動作時,會確認L1 Cache中是否有暫存同一位址的資料,若有,Invalidate L1上的資料,並把該筆更新的資料內容配置到L2 Cache.
WatchDog Reset
在系統設計時,為了避免軟體遇到無法Recovery的錯誤,WatchDog會是系統最後一到防線,而在MPCore架構下,每個處理器都有自己的WatchDog Counter,一旦該Counter太久沒有被踢到,導致Counter倒數為0,就會觸發Reset的機制.目前MPCore提供的Reset設定包括 (所有的設定都為 Active LOW)
名稱
說明
nSCURESET用以Reset MPCore Processor Logic,但並不包括個別MPCore CPU Logic
nCPURESET[3:0]用以Reset目標MPCore CPU Logic (但不包括CP14 Debug Logic)
nWDRESET[3:0]用以Reset WatchDog Reset Status Flag,但如果這次系統Reset,是由特定處理器的WatchDog Reset所觸發,則對應的Status Flag就不會被重置.
nNEONRESET[3:0]
DBGnTRST用以進行DBGTAP reset
nDBGRESET[3:0]
or
nPORESET[3:0]
用以在PowerOn Reset初始化CP14 Debug Logic
RESETREQ[3:0]可針對目標處理器或是所有的處理器,觸發Reset流程被用在WatchDog倒數為0時觸發.
基於上述的設定選項,參考Cortex A9 MPCore文件,Reset總共可以包括以下的組合,其中包括整個MPCoreReset,或是針對個別CPU Logic,以及針對DebugWatchDog Status Flag的動作.
nSCURESET and nPERIPHRESET
nCPURESET[3:0]nNEONRESET[3:0]nDBGRESET[3:0]nWDRESET[3:0]
Cortex-A9 MPCore
Power on reset
0All 0All 0All 0All 0
Cortex-A9 MPCore
Software reset
(CP14 Debug Logic 不做Reset)
0All 0All 0All 1All 0
Per processor
Power on reset
1[n]=0[n]=0[n]=0[n]=0 or All 1
Per processor
Software reset
1[n]=0[n]=0All 1[n]=0 or All 1
SIMD MPE
power on
1All 1All 1All 1All 1
Cortex-A9 MPCore
Debug
1All 1All 1All 0All 1
Per processor
Debug
1All 1All 1[n]=0All 1
Per processor
Watchdog flag
1All 1All 1All 1[n]=0
當作業系統核心遇到無法修復的錯誤時,選擇 MPCore Power on reset讓系統重置,會是比較好的選擇.
Power Management
消費性電子最重要的感受就是功耗,ARM MPCore處理器同樣提供了Run/Standby/Dormany/Shutdown四種電源模式,如下表所示,Wake-Up速度最快的省電模式是Standby Mode,此時處理器的Logic並沒有斷電,相關暫存器與CoProcessor的狀態都維持住,只有處理器進入Clock Gating的狀態若希望包括處理器Logic也斷電,則進一步把相關狀態暫存到處理器TCM,Leakage Current過高,也可採用Shutdown模式,但把記憶體與狀態回存到Storage,在下次Wake-Up,重新回復系統的正常執行.
ModeCortex Processor LogicOnChip RAMWake-Up
RunPower Up 並且所有Logic都有Clock 輸入Power Up
StandbyPower Up但除了Wake-Up Logic,是處於Clock Gating的狀態Power Up此時外部記憶體會進入Low-Power Mode,ARM CPU會處於WFI (Wait For Interrupt)WFE(Wait For Event)狀態,當處理器有收到中斷觸發,Debug Request….etc,就會立刻喚醒.
通常要看SoC本身的Leakage Current,會決定在這狀態下底電流的消耗情況.
Dormant
(最省電的待機狀態)
Power OffRetention state/voltage外部記憶體會進入Low-Power Mode.中斷會透過硬體Wake-Up Module讓處理器Power On,此時處理器要重新初始化,在進入Dormant Mode前處理器的暫存器與相關狀態會儲存在OnChip RAM,通常會透過一個32bits Register記住在OnChip RAMWakeUp後要執行的程式碼記憶體位址,以便醒來後,跳過去執行,恢復進入Dormant Mode前的運作狀態.
ShutdownPower OffPower Off執行完整重新開機的流程.
cortex A9 MPCore四核心的架構來說,總共可以分出14Power Domain,包括
1,針對四個Cortex A9 ProcessorPower Domain (4)
2,針對四個Cortex A9 Processor Data EnginePower Domain (4)
3,針對四個Cortex A9 Processor CacheTLB OnChip RAMPower Domain (4)
4,一個供SCU(Snoop Control Unit) duplicated TAG RAMsPower Domain (1)
5,一個其它Logc(例如:SCU Logic,Private Peripherals..etc)Power Domain (1)
上述Power Domain並不包括SoC中其它週邊的Power Domain(例如:USB Phy/Logic,Storage..etc),如果要達到最佳省電效益的話,就必須要考慮相關應用的軟體行為,搭配對應的PMIC(Power Management IC)Power Group來做區分,維持系統中只有必須的處理器與週邊是Power On與有Clock Input的狀態.
若系統的Standby Dormant Current夠低,在實際的Android手機上,也有快開(Fast-Boot)機制是透過這類機制設計的,讓系統不需要真的走到Shutdown模式,而在下次開機時,又可以非常快的回復到正常運作的模式下.
記憶體管理系統
MMU(Memory Management Unit)主要是負責把虛擬記憶體位址(32-bits 為 0-4GB)對應到實體記憶體中,而在ARM的架構下負責這層對應機制的就是TLB(Translation Lookaside Buffer). 參考ARMTechnical Reference Manual,ARM9,MMU可以支援1MB(Section),64KB(Large Page),4KB(Small Page)1KB(Tiny Page)四種分頁的大小,不過在ARM11Cortex,對應的Mapping Size變為4KB, 64KB, 1MB16MB(Super Section),其中1KB的分頁已經不存在了(應該也是因應目前Application Processor記憶體的實際配置也較大),對分頁與實體記憶體的對應,舉以下例子來說明:使用者在虛擬記憶體位址所使用到的4KB Page,在實體記憶體中就會是連續的實體記憶體區塊,但如果是兩個在虛擬記憶體中連續的4KB Pages,在實體記憶體中就有可能是分離的兩塊實體記憶體區塊,只是因為透過硬體MMU TLB的配置,在虛擬記憶體空間中,應用程式的執行與使用會當成是兩個連續的記憶體區塊.
MMU對多工環境尤其重要,例如在Linux環境中,每個Task都會在自己的虛擬記憶體空間中對應到一組共用的共享函式庫,這些共享函式庫就可以透過MMU把每個Task共用的共享函式內容,用同一塊實體記憶體對應到每個Task各自的虛擬記憶體空間中,如此雖然系統中有多個Task同時運作,但每個Task所共用的記憶體內容部分就可以透過MMU支援對應到同一塊實體記憶體中,減少Run-Time的實體記憶體需求.另一個例子就是,Android DalvikJava應用,每個MMI的應用程式都會基於一個Dalvik VM運作,同時每個VM也都會載入相關動態函式庫.so/.jar,基於MMU的機制,雖然是每個MMI應用都基於一個Dalvik VM,但實際上共用的部份就會透過虛擬記憶體分頁配置對應到同一塊實體記憶體中,降低實際的記憶體需求.
MMU也可以把記憶體範圍依據User ModeKernel Mode設定不同的權限,像是Non-Access,Read Only,Read/Write,如果有發生違反權限的存取行為時,就會導致ARM觸發Abort例外.
ARM平台上,負責查表由虛擬記憶體對應到實體記憶體的動作是由硬體TLB機制來實現的,在單一ARM處理器的架構下,通常只有一個TLB分頁配置位址,也就是說目前Task Context-SwitchTask #A就會把該TaskTLB 分頁配置位址載入,如果是又切換到Task #B就會載入該TaskTLB 分頁配置位址.單核心的架構下,同一時間處理器只會處理一個Task,因此TLB的配置只需要符合這樣的行為即可如下圖所示
然而,在多核心的架構下,同一時間會有多個Task被執行,因此會在每個核心都提供Micro TLB,用以載入目前該核心正在執行中的Task TLB記憶體分頁,並且整個系統會有一組Main TLB,用以同步每個處理器Micro TLB共用的部份.
ARMv7架構為例,要控制TLB Translation Table,可以透過CP15的暫存器c2,其中c2主要提供以下Translation table base registers
名稱
說明
Translation Table Base Register 0 (TTBR0)
用來記錄User-Mode應用Task的記憶體分頁架構所在的Base Address,通常大小為128bytes16kbytes (也就是說每個Task的 1st Level Table可以有324kItems(也就是 1st Level Table Index的最大長度),可透過TTBCR.N值決定),當作業系統進行Context Switch,會把這個暫存器的值,指到新的Task的記憶體分頁架構的Base Address,並更新TTBCRCONTEXTIDR暫存器.如果TTBCR設定為0,則以ARMv6以前的架構來操作 TTBR0.(也就是說只有一個 TTBR,User-ModeKernel-Mode的記憶體分頁都透過它描述,相對的當Context-Switch發生時,就缺少分出TTBR0與 TTBR1的彈性).
Translation Table Base Register 1 (TTBR1)
用來記錄作業系統特權等級與I/O空間的記憶體分頁架構所在的Base Address,屬於這類的記憶體規劃,並不會隨著應用Task Context-Switch而改變.通常這Table大小都為16Kbytes. (就是說 1st Level Table可以有最多 4kItems(= 1st Level Table Index的最大長度)).
Translation Table Base Control Register (TTBCR)
在沒有 Trust Zone Security Extensions支援的環境下,對應的欄位如下所示
31 – 32 – 0
UNK/SBZPN
其中N[2:0] 用以表示TTBR0的寬度,也就是說TTBR0Base Address Bits數為[31:14-N],如果N=0,表示TTBR0對應的Table大小為14bits=16kbytes,如果N=b111=7,表示TTBT0對應的Table大小為7bits=128bytes.
可透過如下指令存取
MRC p15,0,<Rt>,c2,c0,0 ; Read CP15 Translation Table Base Register 0
MCR p15,0,<Rt>,c2,c0,0 ; Write CP15 Translation Table Base Register 0
MRC p15,0,<Rt>,c2,c0,1 ; Read CP15 Translation Table Base Register 1
MCR p15,0,<Rt>,c2,c0,1 ; Write CP15 Translation Table Base Register 1
MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register
MCR p15,0,<Rt>,c2,c0,2 ; Write CP15 Translation Table Base Control Register
有關Domain控制參數,,可以透過CP15的暫存器c3 並取得 Domain Access Control Register 32-bits的值.DACR暫存器只能在特權等級下被存取,該暫存器如下圖所示會以各2 bits被區分為16個欄位.
313029282726252423222120191817161514131211109876543210
D15D14D13D12D11D10D9D8D7D6D5D4D3D2D1D0
每個欄位各2bits的屬性意義如下所示
(
參考這個連結 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0434b/CIHBCBFE.html)
欄位值
說明
b00No access. Any access generates a domain fault.
b01Client Mode. 會對每個存取對應TLB記憶體分頁的動作,執行 Access Permission 的檢查.若有違反權限的存取行為,就會觸發 Permission Fault.
b10Reserved. Any access generates a domain fault.
b11Manager Mode. 將部會對存取記憶體分頁的動作進行Access Permission的檢查,就算該記憶體設定為Read-Only或是eXecute Never(XN),去寫入或是執行,都不會觸發 Permission Fault.
可透過如下指令存取
MRC p15,0,<Rt>,c3,c0,0 ; Read CP15 Domain Access Control Register
MCR p15,0,<Rt>,c3,c0,0 ; Write CP15 Domain Access Control Register
有關處理器切換的Task ID設置,,可以透過CP15的暫存器c13 取得 Context ID Register (CONTEXTIDR) 32-bits的值. CONTEXTIDR對應欄位意義如下所示
31 — 87 — 0
PROCIDASID
欄位說明如下所示
欄位名稱
說明
PROCID用以儲存每個處理器正在執行的Task唯一的識別碼.
ASICApplication Space IDentifier
Address Space Identifier 用以記錄目前使用的記憶體空間識別碼.
可透過如下指令存取
MRC p15,0,<Rt>,c13,c0,1 ; Read CP15 Context ID Register
MCR p15,0,<Rt>,c13,c0,1 ; Write CP15 Context ID Register
除了Task ID本身,CP15c13還提供TPIDRURW (User Read/Write Thread ID Register),
TPIDRURO(User Read-only Thread ID Register),TPIDRPRW(Privileged Only Thread ID Register)分別提供在User-Mode/Kernel Mode Read/Write,User-Mode Read-Only Kernel Mode Read/Write或只有Kernel Mode可以 Read/Write用以設定Thread Id的對應暫存器值.
可透過如下指令存取
MRC p15, 0, <Rt>, c13, c0, 2 ; Read CP15 User Read/Write Thread ID Register
MCR p15, 0, <Rt>, c13, c0, 2 ; Write CP15 User Read/Write Thread ID Register
MRC p15, 0, <Rt>, c13, c0, 3 ; Read CP15 User Read-only Thread ID Register
MCR p15, 0, <Rt>, c13, c0, 3 ; Write CP15 User Read-only Thread ID Register
MRC p15, 0, <Rt>, c13, c0, 4 ; Read CP15 Privileged Only Thread ID Register
MCR p15, 0, <Rt>, c13, c0, 4 ; Write CP15 Privileged Only Thread ID Register
接下來,說明一個32bits虛擬記憶體是如何透過TLB對應到實體記憶體的位址,如下表所示,可以區分為三個部分,分別為12bits的第一級Table Index,10bits的第二級Table Index與最後10bitsPage Index,以此細分最多可以把每個Page的大小細分到 1Kbytes,並對應到完整的4GB虛擬記憶體空間. (2^12 * 2^10 * 1kbytes = 4GB.)
31 — 20 (12-bits)19 – 10 (10 bits)9 – 0 (10bits)
1st Table Index2nd Table IndexPage Index
第一級Table的描述內容如下所示
第二級Table的描述內容如下所示
參考 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babifihd.html , 有關OuterInner Cache在有L1L2 Cache下的定義為 Inner Cache指的就是 L1 Cache,Outer Cache指的就是L2 Cache,而在記憶體分頁的設定中,就可以根據L1L2 Cache的相關行為,決定是否 Cacheable ,Write-Through,Write-Back或是Write-Allocate. 一般而言,L1L2CacheableBufferable行為都會設定成一致,但搭配 TEX,CB欄位,也可以根據系統實際的狀況,L1L2 Cahce可以依據系統所需的行為,而作差異化的調整.
對應欄位的意義說明如下,
欄位名稱
說明
CCacheable
BBufferable
TEX[2:0]TEX
Type Extension (TEX) bit
如下以SCTLR.TRE=0 (透過CP15c1取得 System Control Register 32bits值的bit 28 來設定),也就是TEX Remap disabled模式,來說明記憶體區段屬性的配置與意義.
TEX[2]TEX[1]TEX[0]CB
S
說明
Memory TypePage Shareable
00000XStrongly-orderedStrongly-orderedShareable
00001XShareable DeviceDeviceShareable
00010OOuter and Inner Write-Through, no
Write-Allocate
NormalDepond on S bit
00011OOuter and Inner Write-Back, no Write-AllocateNormalDepond on S bit
00100OOuter and Inner Non-cacheableNormalDepond on S bit
00101XReserved
00110XIMPLEMENTATION DEFINEDIMPLEMENTATION DEFINEDIMPLEMENTATION DEFINED
00111OOuter and Inner Write-Back, Write-AllocateNormalDepond on S bit
01000Non-shareable DeviceDeviceNon-shareable
01001Reserved
0101XReserved
011XXReserved
1BBAAOAA 用來設定Inner Cache(L1 Cache的參數)
BB 用來設定Outer Cachel(L2 Cache的參數)
AABB的編碼值
說明
0 0Non-cacheable
0 1Write-Back, Write-Allocate
1 0Write-Through, no Write-Allocate
1 1Write-Back, no Write-Allocate
NormalDepond on S bit
XNExecute Never 的屬性,若該記憶體分頁 XN Bit設定為1,表示該分頁不會被處理器Fetch指令進來執行,Client Domain (也就是會稽核 Access Permission狀態),記憶體分頁必須要 XN Bit0,且記憶體屬性是設定為可讀取,同時沒有其他Prefech Abort發生的狀態下,才可以被執行如果該記憶體分頁是屬於Manager Domain,XN Bit就不會被當做稽核的條件. (所以就可以嘗試去執行,而不會導致例外發生).
NS這個屬性在支援 Trust Zone Security Extensions環境下,才會有作用.
Domain參考ARMv7的文件, VMSA() 會以4-bits表示DomainIndex,也就是說最大可以定義到16Domain,每個Domain Index會依序對應到Domain Access Control Register 32-bits值中以各2-bits依序產生的16個欄位.
AP[2], AP[1:0]
AP[2]AP[1]AP[0]Privileged
permissions
User
permissions
說明
000No AccessNo AccessAll accesses generate Permission faults
001Read/WriteNo AccessPrivileged access only
010Read/WriteRead OnlyWrites in User mode generate Permission faults
011Read/WriteRead/WriteFull access
100Reserved
101Read OnlyNo AccessPrivileged read-only
110Read OnlyRead OnlyPrivileged and User read-only, deprecated in VMSAv7
111Read OnlyRead OnlyPrivileged and User read-only
S用以定義該記憶體分頁是否為Shareable,S為 表示該記憶體分頁為Non-shareable,S 為 表示該記憶體分頁為 Shareable.
nG這屬性為Non-Global,用來定義該記憶體分頁是否為Global,如果nG0,表示該記憶體分頁為Global,如果為1,表示該記憶體分頁屬於目前正在運作的ASID(Address Space Identifier),該值會對應到正在運作的Task (請參考CONTEXTIDR)
Bit [18]when bits [1:0] == 0b10
0 Descriptor is for a Section
1 Descriptor is for a Supersection.
有關3bits AP (Access Permission)4bits Domain對應的行為,說明如下所示
Manager Domain若 Domain=1,且參考Domain Access Control Register對應到Domain Field 1的值為0b11,也就是Manage Domain,此時如果,AP[2:0]值為0b000,也就是Privileged/User Mode都是 No Access,由於此時為Manager Domain,因此對任何記憶體範圍的存取都不會進行權限的檢查動作,因此不管此時是處於Privileged/User Mode,都可以對該記憶體內容進行存取的動作.
Client Domain若 Domain=2,且參考Domain Access Control Register對應到Domain Field 2的值為0b01,也就是Client Domain,此時如果,AP[2:0]值為0b010,也就是Privileged Mode為 Read/Write,User ModeRead Only.
如果此時CPU處於Privileged Mode,可以對該記憶體進行讀寫
若此時CPU處於User Mode,則只允許對該記憶體進行讀取,寫入的動作會導致Permission faults
Client Domain若 Domain=3,且參考Domain Access Control Register對應到Domain Field 3的值為0b01,也就是Client Domain,此時如果,AP[2:0]值為0b001,也就是Privileged Mode為 Read/Write,User ModeNo Access.
如果此時CPU處於Privileged Mode,可以對該記憶體進行讀寫
若此時CPU處於User Mode,對該記憶體的存取動作,都會導致Permission faults
根據TLB的設定參數組合,接下來分別以基於16MB(SuperSection),1MB(Section),64KB(Large Page),4KB(Small Page)1KB(Tiny Page)不同分頁的組合,來說明TLB 1級與2級 Table的運作概念,
如下所示為16MB(SuperSection) 配置下,TLB分頁運作的概念
如下所示為1MB(Section) 配置下,TLB分頁運作的概念
如下所示為64KB(Large Page) 配置下,TLB分頁運作的概念

如下所示為4KB(Small Page) 配置下,TLB分頁運作的概念

如下所示為1KB(Tiny Page) 配置下,TLB分頁運作的概念

Fast Context-Switch Extension (FCSE)

快速行程切換主要支援以32MB記憶體範圍為單位,Virtual Address轉為Modified Virtual Address對應的空間,如下圖所示,虛擬記憶體位址會透過FCSE邏輯,轉為修正後的虛擬記憶體位址,再透過MMU對應到實體記憶體空間(Physical Memory Address),也就是說,基於FCSE整個系統可以共用同一份虛擬記憶體空間配置表,不需要在每個Task切換時,更新整個虛擬記憶體空間配置表,只需要把各自對應的32MB起點位置透過FCSE對應到目前所在虛擬記憶體空間的對應位置(Modified Virtual Memory Address)即可.

FCSE最多只能切割12832MB記憶體空間,並對應到4GB的虛擬記憶體配置,同時,每個Task各自擁有的虛擬記憶體空間必須是0x00000000起點的記憶體位置,並依據7bitsPID來對應到各自的32MB記憶體區塊,運作行為可用以下的簡式來說明
if(VA[31:25] ==0) then
MVA = VA | (PID<<25)
else
MVA = VA
參考ARM1176JZ-S Technical Reference Manual,ARM為了讓早期Windows CE 每個行程各自32MB虛擬記憶體空間的設計,可以有效的運作,因此提供了快速行程切換(FCSE)機制.當發生Task切換時,可以透過設定CP15 c13 暫存器中FCSE PID的值,決定FCSE所要轉換的記憶體空間,對應帶來的好處就是,由於整個系統在Task切換後,還是基於同一份TLB的虛擬記憶體配置表,同時配置表中的內容仍舊是有效的,只是透過FCSE把運作的Task虛擬32MB記憶體空間轉換到對應的位置,因此,可以減少TLB Flush的成本,減少Task Context-Switch切換的成本.
可透過如下程式碼讀/FCSE PID
MRC p15, 0, <Rd>, c13, c0, 0; Read FCSE PID Register
MCR p15, 0, <Rd>, c13, c0, 0; Write FCSE PID Register
暫存器格式如下所示
313029282726252423222120191817161514131211109876543210
FCSE PIDSBZ
參考網頁http://en.wikipedia.org/wiki/Windows_Embedded_CE_6.0 的說明 ,Windows CE 6以前,每個應用程式只能擁有屬於各自32MB的虛擬記憶體空間,並且最多只能有32Tasks被載入到記憶體中到了Windows CE 6之後的核心,選擇支援完整的記憶體分頁機制,提供每個Task各自2GB的虛擬記憶體空間,並支援最多32768 (2^15)Tasks被載入到記憶體中對應到Windows Mobile的版本,則是直到Windows Phone 7 才採用Windows CE 6.0 R3的核心,解除了每個應用程式32MB虛擬記憶體的限制.
ARMARM11(ARMv6)並不建議採用FCSE,而在Cortex (ARMv7)方案中,FCSE為一個Optional選項.
Micro TLBMain TLB(Translation Lookaside Buffer)架構
參考相關Two-Level TLB (Micro/Main)架構的文件,為了要減少TLB查詢對外部記憶體存取的成本,因此在On-Chip上增加SRAM,透過高速的記憶體,Micro TLB可以在1CPU Clock就完成查詢的結果,Miss,才是到Main TLB查詢,若還是Miss,才是到外部記憶體上的TLB查詢另外這篇論文 “An Advanced Filtering TLB for Low Power Consumption”(參考網址:http://supercom.yonsei.ac.kr/paper/An%20advanced%20filtering%20TLB%20for%20low%20power%20consumption.pdf ),Strong ARM為例(記憶中時脈約為200MHz),在功耗的消耗上,個記憶體區塊大約各佔Instruction Cache:27%,TLB(Translation Lookaside Buffer ):17%Data Cache:16%,由此可知Instruction CacheTLB在處理器運作時,是相當頻繁被存取使用的.同時,Micro/Main TLB支援筆數增加,虛擬記憶體查詢Miss Rate就會降低,且對外部記憶體TLB查詢的次數減少,也可降低功耗.
TLB本身為一個On-Chip的記憶體區塊,當處理器要去查詢外部記憶體的記憶體分頁表格時,如果要查詢的目的記憶體位址存在於TLB暫存的記憶體中,就會由TLB直接返回,反之如果該記憶體位置不在目前TLB暫存的範圍中,就會到外部記憶體分頁表格中查詢,並且把查詢的結果記錄到TLB,以便在下次又查詢同樣的記憶體位址時,可以很快速的回應,省去要到外部記憶體查詢的成本.
當外部記憶體的記憶體分頁表格因為 Task Context-Switch切換而變動時,我們會透過CP15 c2暫存器來修改TLB Base Address,並且Flush TLB快取暫存中的內容(因為已經對應到新的Task記憶體分頁內容),相關Flush的動作可以透過CP15 c8暫存器來執行,如果有些虛擬記憶體對應的內容並不希望因為Task Context-Switch切換,TLB Flush所清除,則可以透過CP15 c10暫存器,進行TLB Lock-Down的動作,讓該記憶體對應位址的內容可以保存在TLB暫存記憶體中,進而加入相關記憶體轉換的速度.
Cortex A(ARMv7)Virtual Memory System Architecture 對記憶體管理部分有如下的演進,
1,記憶體分頁包括4KB,64KB,1MB16MB.
2,支援記憶體分頁16Domains
3,支援記憶體分頁GlobalASID(Address space identifiers)機制,避免當Task Context-Switch發生時,TLBFlush的成本. (屬於Global的分頁是不屬於特定的Task,ASID 8-bits可用來識別不同Task記憶體配置的ID)
4,延伸Access Permission的能力,
Cortex A9,為了支援多核心的架構,記憶體管理機制做了以下的演進,
1,支援32筆項目的Instruction Micro TLB
2,支援32筆項目的Data Micro TLB
3,支援一致的Main TLB
4,支援L1 Data CachePage Table查詢硬體. (可以用來確保每個處理器L1 Data Cache共用的Page一致性.)
在多核心的架構下,ARM為了減少每個處理器出去外部TLB查詢Table的次數,因此提供了2 LevelTLB架構(MicroMain TLB),
Micro TLB每個處理器都會有自己的Micro TLB,提供InstructionData32筆對應的項目(ARM11 MPCore為各八筆),可以在1CPU CycleVirtual Address轉為Physical Address,包括該記憶體分頁的保護屬性,或是否要觸發Prefech/Data Abort.如果該Virtual Address不在這InstructionData TLB 的紀錄中,就會往Main TLB查詢.
如果外部的Main TLB有更新,或是發生Task Context-Switch 更新Context ID Register都會導致Micro TLBFlush.
Main TLBMain TLB可以對應到16MB,1MB,64KB4KB不同的記憶體分頁,一旦所要查詢的Virtual AddressMicro TLB中查詢不到,就會到Main TLB中查詢. Main TLB2 ways的配置,可以為2*3264筆項目的Main TLB,2*64128筆項目的Main TLB. 每個Main TLB項目都會包括
1,Virtual Address
2,Page Size
3,Physical Address
4,Memory Properties
每一組上述的項目,都會對應到一個特定的Application空間,或是Global讓全系統共享,每個ARM核心都會透過設定CONTEXIDR暫存器,記錄目前該核心所運作的Application空間,每次TLB項目比對時,只要符合以下條件就算是對比成功
1,虛擬記憶體跟TLB項目一致 (bits長度可為[31:N],要視記憶體分頁大小而定)
2,Non-secure TLB ID (NSTID)跟目前Secure狀態一致. (在有支援Trust Zone Security Extension的環境)
3,TLB中的ASID跟目標Task ASID一致或是為Global數性.
其它有關Main TLB lockdown 相關暫存器,如下所示
MCR p15,5,<Rd>,c15,c4,2 #Select Lockdown TLB Entry for Read (Main TLB Index)
MCR p15,5,<Rd>,c15,c4,4 #Select Lockdown TLB Entry for Write (Main TLB Index)
MRC p15,5,<Rd>,c15,c5,2 #Read Lockdown TLB VA Register Data
MCR p15,5,<Rd>,c15,c5,2 #Write Lockdown TLB VA Register Data
MRC p15,5,<Rd>,c15,c6,2 #Read Lockdown TLB PA Register Data
MCR p15,5,<Rd>,c15,c6,2 #Write Lockdown TLB PA Register Data
MRC p15,5,<Rd>,c15,c7,2 #Read Lockdown TLB attributes Register Data
MCR p15,5,<Rd>,c15,c7,2 #Write Lockdown TLB attributes Register Data
結語
隨著Smart Phone與平板市場的風行,ARM MPCore架構絕對會是最受矚目的方案,尤其,包括Android上用NDK開發的應用,或是其它基於ARM平台的方案,都讓ARM處理器累積了大量專屬的應用與越來越難以取代的角色.
本文主要以筆者所需的資訊為主來彙整,ARM MPCore有更進一步需求的開發者,請自行參閱ARM MPCore技術文件.