作者簡介
baron (網名:代碼改變世界ctw),九年手機安全/SOC底層安全開發經驗。擅長trustzone/tee安全產品的設計和開發
1.序言
帶著問題去學習,關于cache的一些思考:1、L1/L2/L3 cache到底在哪里?L1/L2/L3 cache分別都是多大?2、L1/L2/L3 cache的組織形式都是怎樣的?n路組相連?3、你見過VIVT的cache嗎?你為什么要學習VIVT的cache?非常干擾你對cache的理解,還不如不學呢.4、那么cache是VIPT還是PIPT?還是在一個core中既有VIPT,也有PIPT?5、你要學習MESI的原理嗎?你能記得住嗎?你是不懂MESI,還是不懂cache架構?6、MOESI又是啥玩意?現在主流的core是MESI,還是MOESI?7、MESI僅僅是一個協議,總得有硬件來執行這個協議,硬件是誰?8、MESI這個協議有4個狀態,這4個狀態記錄在哪里?9、L1/L2/L3 cache中,或者說core cache/cluster cache中,哪些cache的維護遵守了MESI協議,哪些沒有遵守?為什么這樣設計?10、cache line中的data是多少個字節?在分析問題時,你為什么總是按照條件分析,16bytes的cache line是怎樣的,64bytes的cacheline是怎樣的?難道你不知道,現在主流的arm core的cache line全部都是64bytes?11、cache的TAG是什么玩意,里面都有什么?別說cache TAG是物理地址?12、cache line中又都有什么? 為什么沒有index?13、L2 cache到底是在core中,還是在cluster中?14、假設一塊內存配置成了non-cacheable,為什么就不緩存到cache了?15、頁表entry的屬性中定義了cache的緩存策略,那如果disable mmu后,那么cpu讀寫內存時候的緩存策略是什么?16、做為一名軟件工程師,對于L1/L2/L3 cache的緩存策略,哪些可以修改?哪些是硬件定死的不可以修改?而這些的替換策略又都是怎樣的?17、什么是inclusive cache?什么是exclusive cache?Strictly和Weakly呢?18、一些概念的理解,如CCI、SCU、DSU、ACE、CHI ?19、如何配置一個頁面的cacheable屬性?如何配置頁表的cacheable屬性?
2.前言
做為一名底層安全工程師、一名一線支持客戶的FAE,工作的內容涉及到TF-A、TEE、TA、Linux Kernel、Linux native程序等眾多模塊,也會涉及到一些硬件模塊driver。在這些不同的硬件或系統軟件之中,有著不同的memory屬性的配置,不同的緩存策略,那么我們在這多硬件多軟件通過share memory通信時,就會遇到各種各樣的問題,其實很多時候,也都是客戶的靈魂一問,為了給客戶一個專業的感覺,身為FAE也不得不去弄懂底層深層次的原理....
本人不是什么專家,更不是什么的大佬,也就是看了一些arm文檔,加上自己的理解,然后總結出如下文章,當然我在總結的時候,一切都以官方資料為準,盡量不瞎說不亂說,有些查不到的資料我求證了一些ASIC專家。其實cache同其它模塊(如MMU、異常、gic...)相比,cache應該算上最難的,不過好在它的大多數行為都是硬件幫我們做好了,所以我們軟件就簡單了,但是越是硬件自動的行為,對于我們軟件工程師理解起來就會吃力,因為看不到資料看不到設計,很多都得靠猜。
最后,希望這系列文章,能夠對大家有所幫助。好好學習、天天向上,卷起來同志們。
說明:
本系列所講述的,都是以armv8/armv9架構位基準,如有涉及執行狀態,則是aarch64. 如有涉及具體core,則是A710和A53
大多數內容來自arm官方文檔、少部分咨詢了ASIC同事,再加上部分自己的理解...
3.為什么要用cache?
ARM 架構剛開始開發時,處理器的時鐘速度和內存的訪問速度大致相似。今天的處理器內核要復雜得多,并且時鐘頻率可以快幾個數量級。然而,外部總線和存儲設備的頻率并沒有達到同樣的程度??梢詫崿F可以與內核以相同速度運行的小片上 SRAM塊,但與標準 DRAM 塊相比,這種 RAM 非常昂貴,標準 DRAM 塊的容量可能高出數千倍。在許多基于 ARM 處理器的系統中,訪問外部存儲器需要數十甚至數百個內核周期。
高速緩存是位于核心和主內存之間的小而快速的內存塊。它在主內存中保存項目的副本。對高速緩沖存儲器的訪問比對主存儲器的訪問快得多。每當內核讀取或寫入特定地址時,它首先會在緩存中查找。如果它在高速緩存中找到地址,它就使用高速緩存中的數據,而不是執行對主存儲器的訪問。通過減少緩慢的外部存儲器訪問時間的影響,這顯著提高了系統的潛在性能。通過避免驅動外部信號的需要,它還降低了系統的功耗
4.為什么要學習cache呢?
cache和我們軟件工程師有啥關系?其實在很多時候,硬件都會自動去維護cache和內存直接的一致性,這和我們軟件工程師都沒有太大的關系,所以很多時候我們也無需去理解cache的原理。但是實就是事實,不管你有沒有理解,你都是一直在使用的。做為一名底層的軟件開發者,有些時候,你也不得不去主動刷新cache,即軟件中維護內存一致性 。那么一般什么時候需要主動刷cache呢(軟件中維護內存一致性) ? 以下便舉了幾個最常見的示例。
4.1 不同的Master硬件共享數據時
例如一個core和一個crypto engine硬件,在共享數據的時候。需要軟件主動去invalid或flush cache的操作。
4.1.1 軟件中維護內存一致性 – flush cache
4.1.2 軟件中維護內存一致性 – invalid cache
4.2 不同的緩存策略的系統共享數據時
例如在一個TEE + linux的系統中,且兩個系統有著不同的緩存策略。如linux kernel中是outer cacheable,TEE中是non-cacheable
4.2.1 軟件中維護內存一致性 – flush cache
4.2.2 軟件中維護內存一致性 – invalid cache
5.怎么去刷cache呢?(軟件維護cache的一致性)
ARM提供了操作cache的指令, 軟件維護操作cache的指令有三類:
Invalidation:其實就是修改valid bit,讓cache無效。
Cleaning:清除cache中的data和TAG,這其實就是我們所說的flush cache,這里會將cache數據回寫到內存,并清除dirty標志
Zero:將cache中的數據清0.
那么一般什么時候需要軟件維護cache一致性呢?:(1)、當有其它的Master改變的external memory,如DMA操作(2)、MMU的enable或disable的整個區間的內存訪問,(3)、當不同緩存策略的系統使用同一塊內存通信時,如REE enable了mmu,TEE disable了mmu.
針對第(2)點,cache怎么和mmu扯上關系了呢?那是因為: mmu的開啟和關閉,影響了內存的permissions, cache policies
5.1 cache一致性指令介紹
查閱armv8/armv9的aarch64體系中,定義了如下的緩存一致性操作指令指令太多,不太好記,然后我們總結如下:按照指令,分為:
IC : 操作instruction cache
DC : 操作data cache
按照操作,分為以下三類:
Invalidation:其實就是修改valid bit,讓cache無效。
Cleaning:清除cache中的data和TAG,這其實就是我們所說的flush cache,這里會將cache數據回寫到內存,并清除dirty標志
Zero:將cache中的數據清0.
Points的定義:其描述的是操作cache的范圍
Point of Coherency (PoC) :instruction、data、TLB訪問一致性的點
Point of Unification (PoU) :agents訪問內存一致性的點
Point of Persistence (PoP) :和FEATDPB、FEATDPB2 feature相關
Point of Deep Persistence (PoDP) :訪問memory一致性的點
5.2 cache一致性指令的使用示例
5.3 操作系統中軟件維護cache一致性的API
在操作系統中,我們只需要調用相關的API即可,也無需牢記以上的維護cache一致性的命令。
比如在Linux Kernel 操作Cache的API如下所示:
linux/arch/arm64/mm/cache.S
linux/arch/arm64/include/asm/cacheflush.h
void __flush_icache_range(unsignedlong start, unsignedlong end);
int invalidate_icache_range(unsignedlong start, unsignedlong end);
void __flush_dcache_area(void*addr, size_t len);
void __inval_dcache_area(void*addr, size_t len);
void __clean_dcache_area_poc(void*addr, size_t len);
void __clean_dcache_area_pop(void*addr, size_t len);
void __clean_dcache_area_pou(void*addr, size_t len);
long __flush_cache_user_range(unsignedlong start, unsignedlong end);
void sync_icache_aliases(void*kaddr, unsignedlong len);
void flush_icache_range(unsignedlong start, unsignedlong end)
void __flush_icache_all(void)
原文標題:深入學習Cache系列 1: 帶著幾個疑問,從Cache的應用場景學起
文章出處:【微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。
-
軟件
+關注
關注
69文章
4969瀏覽量
87702 -
開發
+關注
關注
0文章
370瀏覽量
40872 -
高速緩沖存儲器
+關注
關注
0文章
12瀏覽量
7532
原文標題:深入學習Cache系列 1: 帶著幾個疑問,從Cache的應用場景學起
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論