Trace32支持一系列的SMMU命令,可以幫助用戶更好地配置、查看和分析SMMU。換句話說,就是讓SMMU的配置變得可視化。
在添加SMMU實例之前,需要選擇一個CPU來激活該SMMU實例的相關命令。Trace32讓SMMU的配置可視化的本質是,操縱CPU讀取SMMU的寄存器,然后進行解碼顯示。
下面的代碼是一個最基本的示例,先選擇CPU type,然后添加SMMU實例:
SYStem.CPU CortexA53 ;for example, the ‘CortexA53’ CPU is SMMU-capable
SMMU.ADD ... ;you can now define an SMMU, e.g. an SMMU for a graphics processing unit (GPU)
當然也有一些SOC CPU將SMMU預定義成了一個組件,可以直接在SYStem.CONFIG窗口里看見。
Trace32支持MMU-400, MMU-401 ,MMU-500 和 MMU-600,其中MMU-500指的是ARM SMMU架構第二代,簡稱SMMUv2,MMU-600指的是ARM SMMU架構第三代,簡稱SMMUv3。
Trace32的SMMU 相關命令帶來的最大好處是,將SMMU的配置可視化,其中包括:
- SMMU相關配置寄存器,總結起來有三大部分:Stream mapping table相關寄存器;TCU相關寄存器(global);Context Bank相關寄存器。
- Pagetable的可視化,其中包括dump和list
- Stream mapping table的可視化。
下面我們以SMMUv2為例,解釋Trace32 SMMU相關指令的用法。讓Trace32顯示SMMU的stream mapping table(或稱Stream table),是一個最基本的做法,并且可以通過這個stream table打開SMMU其他配置功能窗口。
- A 為stream table的完整窗口.
- B Each row stands for a stream map register group (SMRG). 比如在SMMUv2中的Stream mapping table里,最多支持128個entry,也就是SMR和S2CR等寄存器有128個,即reg.grp index可以是從0x0到0x7F。
- C Index of a translation context bank. 通過S2CR寄存器可以指定當前這個stream entry指定的是哪個CB.
- D Data from stream matching registers. 這部分信息來自SMR寄存器,通過這個寄存器可以知道傳入的stream id是否 match該entry。
下面筆者將總結Trace32常用的SMMU指令。
Trace32常用的SMMU指令
- 一,SMMU實例創建: SMMU.ADD
- <name>
- <smmu_type>
- <base_address>
- 二,SMMU實例刪除:SMMU.Clear <name> 和 SMMU.RESet
- 三,SMMU 寄存器可視化:SMMU.Register
- SMMU.Register.Global
- SMMU.Register.ContextBank
- SMMU.Register.StreamMapRegGrp
- 四,SMMU pagetable的可視化:SMMU.StreamMapRegGrp
- SMMU.StreamMapRegGrp.ContextReg
- SMMU.StreamMapRegGrp.Dump 和 SMMU.StreamMapRegGrp.list
- 五,SMMU.StreamTable 或者 SMMU.StreamMapTable
- stream matching的硬件邏輯
- Trace32 stream matching 函數:SMMU.StreamID2SMRG()
- Stream Table窗口 顯示字段詳解
- 六,SMMU Global Faults 或者 Global Errors 的顯示
一,SMMU實例創建: SMMU.ADD
用于定義一個新的SMMU實例,Trace32最多支持添加20個SMMU 實例,
Format: SMMU.ADD "<name>" <smmu_type> <base_address>
它需要傳入三個參數:
為SMMU實例設置一個獨一無二的名字是必須的,名字不能超過9個字符長度,并且需要用雙引號括起來,但是這只針對于SMMU.ADD指令,在執行完SMMU.ADD后,之后對該實例操作的SMMU指令不需要使用雙引號。
<smmu_type>
用于指定SMMU的類型:<smmu_type>: MMU400 | MMU401 | MMU500 | MMU600
<base_address>
這是SMMU寄存器空間的基址,如果SMMU支持secure和non-secure兩種安全狀態,那么我們可以在這個基址前加上訪問類型的修飾符,比如表示以CPU secure狀態下去訪問,可以用AZSD: 或者 ZSD:,以CPU non-secure去訪問,則使用 NSD:, NUD:, HD:。需要注意的是Trace32訪問SMMU空間,是以CPU為主體進行訪問的,所以訪問類型不可以是AXI這種。
以下是一個具體的使用實例:
;define a new SMMU named "myGPU" for a graphics processing unit
SMMU.ADD "myGPU" MMU500 AZSD:0x50000000
;display the stream table of the SMMU named “myGPU”
SMMU.StreamTable myGPU
二,SMMU實例刪除:SMMU.Clear 和 SMMU.RESet
clear 和reset都可以刪除之前用SMMU.ADD創建的SMMU實例,不同的是,clear只能刪除指定的那一個,而reset可以刪除所有的實例。
三,SMMU 寄存器可視化:SMMU.Register
通過Trace32的 SMMU.Register指令,可以可視化SMMU里最主要的三部分寄存器:
- TCU部分,也就是Global部分,用于控制全局的SMMU配置。
- CB部分,用于配置Context bank相關的寄存器。
- SMR部分,主要用于stream matching,包括SMR和S2CR。
這三部分寄存器的內容都可以通過Trace32命令顯示出來。
SMMU.Register.Global
用于顯示SMMU global寄存器,用法如下:
SMMU.Register.Global <name>
SMMU.Register.ContextBank
用于顯示CB相關的寄存器,需要指定CB的index,MMU-400, MMU-401 and MMU-500 only.
用法如下:
SMMU.Register.ContextBank <name> <cbndx>
SMMU.Register.ContextBank myGPU 0x16
SMMU.Register.StreamMapRegGrp
關于Stream mapping,也有兩個關鍵寄存器SMR和S2CR,需要指定Stream table entry的index,MMU-400, MMU-401 and MMU-500 only.
用法如下:
SMMU.StreamMapRegGrp.Register myGPU 0x06
除了使用相關命令之外,還可以在打開的Streamtable窗口下,選中指定的Stream table entry后,直接右鍵打開菜單進行操作:
四,SMMU pagetable的可視化:SMMU.StreamMapRegGrp
通過SMMU.StreamMapRegGrp命令可以打開SMMU指定SMR index的pagetable。
我們先捋一下邏輯,如下圖所示,一筆帶有stream ID的transaction進入SMMU,首先在stream mapping table里進行stream matching,它會遍歷SMT里的所有SMR,逐一進行匹配,匹配成功后,比如匹配上SMR0,再通過S2CR0寄存器里先前指定好的CBNDX,選擇CB,而pagetable的基址就保存在CB的TTBR里。所以通過傳入SMR的index來可視化pagetable的本質是:讀取對應S2CR寄存器找到指定的CB,再從該CB里找到pagetable的基址進行解碼。
SMMU.StreamMapRegGrp指令有三個選項:
- SMMU.StreamMapRegGrp.ContextReg, Shows the registers of the context bank associated with the stage 1 and/or stage 2 translation.
- SMMU.StreamMapRegGrp.Dump Dumps the page table associated with the stage 1 and/or stage 2 translation page wise.
- SMMU.StreamMapRegGrp.list Lists the page table entries associated with the stage 1 and/or stage 2 translation in a compact format.
SMMU.StreamMapRegGrp.ContextReg
SMMU.StreamMapRegGrp.ContextReg和SMMU.Register.ContextBank 這兩個指令都可以將CB的配置寄存器顯示出來,但是也有一點不同:
- SMMU.Register.ContextBank 傳入的參數是 CBNDX,CB的index,直接指定CB進行顯示。
- SMMU.StreamMapRegGrp.ContextReg 傳入的參數是 SMRG_INDEX, stream table entry的index,正如我上文提到過,通過 SMRG_INDEX找到S2CR,然后讀取對應S2CR寄存器找到指定的CB,屬于間接訪問,并且還可以增加 /IntermediatePT 選項,來選擇顯示 stage1 還是 stage2的CB。
SMMU.StreamMapRegGrp.Dump 和 SMMU.StreamMapRegGrp.list
SMMU.StreamMapRegGrp.Dump 和 SMMU.StreamMapRegGrp.list這兩個指令,傳入smrg_index參數用來選擇stream table entry,并將該entry里指定的CB 的pagetable解碼出來。
Format: SMMU.StreamMapRegGrp.Dump <args>
<args>: <name> <smrg_index> [<address> | <range> [<ttb_address>]] [/<option>]Format: SMMU.StreamMapRegGrp.list <args>
<args>: <name> <smrg_index> [<address> | <range> [<ttb_address>]] [/IntermediatePT]
SMMU.StreamMapRegGrp.Dump命令需要指定SMMU實例的名字以及Stream mapping table的index。如果沒有指定地址或者范圍,默認是dump所有的內容。其中還可以指定ttb_address,也就是Pagetable 的基址,如果沒有指定,那就從SMRG中抽取。intermediatePT 選項主要用于Stage2,對于stage1,它將被忽略。
SMMU.StreamMapRegGrp.Dump myGPU 0x0C
也可以直接右鍵打開list和dump窗口:
以下是smmu Pagetable dump窗口顯示出的個字段釋義:
五,SMMU.StreamTable 或者 SMMU.StreamMapTable
SMMU.StreamTable 或者 SMMU.StreamMapTable,二者是等同的,
Format: SMMU.StreamTable <args>
SMMU.StreamMapTable <args> (as an alias)
<args>: <name> [/StreamID <value>]
(for MMU-400, MMU-401 and MMU-500)
SMMU.StreamTable命令可以傳入 StreamID到Stream table里進行匹配,Trace32的Stream ID匹配邏輯是模擬真實的SMMU硬件邏輯做的。原理就是將該StreamID與所有StreamTable SMR寄存器里的ID和mask進行匹配,如果匹配成功,則會高亮該Stream table entry。
;define a new SMMU named "myGPU" for a graphics processing unit
SMMU.ADD "myGPU" MMU500 AZSD:0x50000000
;open the window and highlight the matching SMRG in yellow
SMMU.StreamTable myGPU /StreamID 0x324A
stream matching的硬件邏輯
這里簡單介紹一下stream matching的硬件邏輯,stream ID的匹配主要是根據 SMR寄存器里的三個字段:valid,id 和mask進行的。valid為1,說明該stream table entry有效,可以進行stream matching。比如傳入的stream ID為0x324A ,SMR.id = 0x24A, SMR.mask=0x7000,匹配是否會成功?
首先看 mask 字段,0x7000 = 0y0111_0000_0000_0000, 這說明 傳入的streamID的第12,13,14三個bit不會參與stream matching, 換言之,這三個bit會被忽略,stream ID 0x324A 將這三個bit忽略后,變成0x24A, 與SMR.id = 0x24A相同,所以匹配成功。
Trace32 stream matching 函數:SMMU.StreamID2SMRG()
Trace32提供了一個 stream matching 函數:SMMU.StreamID2SMRG(name, stream_id),通過傳入SMMU實例的名字,以及需要匹配的stream ID,來查找是否有匹配成功的stream table entry。
SMMU.StreamID2SMRG()的返回值有三種情況:
- 沒有匹配上,返回 -1
- 匹配上了多個SMT entry,返回 -2
- 有且只匹配上了一個,返回對應entry的index,比如有128個entry,那么返回值在0到127之間。
使用示例:
;open the window and highlight the matching SMRG in yellow
SMMU.StreamMapTable myGPU /StreamID 0x3464
;return the index of the SMRG as a decimal value
&index=SMMU.StreamID2SMRG("myGPU",0x3464)
;print the index as hex and decimal to the AREA window
PRINT "hex: 0x" CONVert.INTTOHEX(&index) " decimal: &index"
AREA.view
Stream Table窗口 顯示字段詳解
六,SMMU Global Faults 或者 Global Errors 的顯示
如下圖所示,Trace32的SMMU.StreamTable窗口可以顯示 SMMU的 Global faults,其原理就是解碼SMMU_sGFSR寄存器,該寄存器里保存著各種Global faults的狀態信息。
關于 CB的錯誤信息,SMMU.StreamTable窗口里也有顯示,在state列中以一個紅色字母,比如 F,M或者S顯示: