昨天读了 baron 大佬写的介绍 cache 细节的文档,天哪,太详细了,简直面面俱到~ 大佬就是大佬。
看完不禁想起我在 csdn 博客上公开发表的第一篇文章,关于 cache 何时需要对作废、何时需要刷新的分析说明,原文写于 2016 年,忍不住在这里分享一下,比较简单,希望对 cache 操作不了解的朋友有些帮助。
baron 写了很多安全方面的文章,自谦是非著名的trustzone/tee/安全渣渣,研究方向包括 arm trustzone、tee, 各种 linux 和 android 安全, csdn 博客地址: https://blog.csdn.net/weixin_42135087
1. 什么是 cache?
高速缓存(cache)主要是为了解决cpu运算速度与内存(memory)读写速度不匹配的矛盾而存在, 是cpu与内存之间的临时存贮器,容量小,但是交换速度比内存快。
百度百科是这样介绍缓存的:
cpu要读取一个数据时,首先从cache中查找,如果找到就立即读取并送给cpu处理;如果没有找到,就用相对慢的速度从内存中读取并送给cpu处理,同时把这个数据所在的数据块调入cache中,可以使得以后对整块数据的读取都从cache中进行,不必再调用内存。
正是这样的读取机制使cpu读取cache的命中率非常高(大多数cpu可达90%左右),也就是说cpu下一次要读取的数据90%都在cache中,只有大约10%需要从内存读取。这大大节省了cpu直接读取内存的时间,也使cpu读取数据时基本无需等待。总的来说,cpu读取数据的顺序是先cache后内存。
2. cache 的分类
cache 的硬件实现中通常包含一级 cache(l1 cache),二级 cache(l2 cache)甚至多级 cache;
对于一级cache,又有 instruction cache(指令缓存,通常称为 i-cache)和 data cache(数据缓存,通常称为 d-cache)之分,本文准备不讨论各级 cache 的区别以及 i-cache 和 d-cache 的细节,仅将这些所有实现笼统称为cache。
本文仅针对 cache 的读写进行简单说明并通过示意图演示什么时候需要写回(flush)缓存,什么时候需要作废(invalidate)缓存。
目前我所知的非常强的一款 cpu: amd ryzen 3970x (线程撕裂者) 32 核心 64 线程,其一级缓存 3mb, 二级缓存 16mb, 三级缓存 128mb, 有朋友用这颗芯片配置了一台个人电脑,编译最新的 android s (12) 只要 20 多分钟,绝大部分公司的服务器还做不到这个性能。
对于指令缓存的 i-cache 和数据缓存的 d-cache,平时 d-cache 访问比较多,以下主要以 d-cache 的访问为例说明,指令缓存 i-cache 原理一样。
3. cache 数据访问原理
cache读写原理
图一、cache读写原理
写入数据时:
第一步,cpu 将数据写入 cache;
第二步,将 cache 数据传送到 memory 中相应的位置;
读取数据时:
第一步,将 memory 中的数据传送到 cache 中;
第二步,cpu 从 cache 中读取数据;
在具体的硬件实现上,cache 有写操作有透写(write-through)和回写(write-back)两种方式:
透写(write-through)
在透写式 cache 中,cpu 的数据总是写入到内存中,如果对应内存位置的数据在 cache 中有一个备份,那么这个备份也要更新,保证内存和 cache 中的数据永远同步。所以每次操作总会执行图一中的步骤 1 和 2。
回写(write-back)
在回写式 cache 中,把要写的数据只写到 cache 中,并对 cache 对应的位置做一个标记,只在必要的时候才会将数据更新到内存中。所以每次写操作都会执行步骤中的图 1,但并不是每次执行步骤 1 后都执行步骤 2 操作。
透写方式存在性能瓶颈,性能低于回写方式,现在的 cpu 设计基本上都是采用 cache 回写方式。
通常情况下,数据只通过 cpu 进行访问,每次访问都会经过 cache,此时数据同步不会有问题。
在有设备进行 dma 操作的情况下,设备读写数据不再通过 cache,而是直接访问内存。在设备和 cpu 读写同一块内存时,所取得的数据可能会不一致,如图二。
设备和cpu读写同一块内存时数据不一致
图二、设备和cpu读写同一块内存时数据不一致
cpu 执行步骤1将数据 a 写入 cache,但并不是每次都会执行步骤 2 将数据 a 同步到内存,导致 cache 中的数据 a 和内存中的数据 a’不一致;步骤 3 中,外部设备通过 dma 操作时直接从内存访问数据,从而取得的是a’而不是a。
设备dma操作完成后,通过步骤 4 将数据 b 写入内存;但是由于内存中的数据不会和 cache 自动进行同步,步骤 5不会被执行,所以 cpu 执行步骤 3 读取数据时,获取的可能是 cache 中的数据 b’,而不是内存中的数据b;
在 cpu 和外设访问同一片内存区域的情况下,如何操作 cache 以确保设备和 cpu 访问的数据一致就显得尤为重要,见图三。
cache操作同步数据
图三、cache操作同步数据
cpu 执行步骤 1 将数据 a 写入 cache,由于设备也需要访问数据 a,因此执行步骤 2 将数据 a 通过 flush 操作同步到内存;步骤 3 中,外部设备通过 dma 操作时直接从内存访问数据 a,最终 cpu 和设备访问的都是相同的数据。
设备 dma 操作完成后,通过步骤 4 将数据 b 写入内存;由于 cpu 也需要访问数据 b,访问前通过 invalidate 操作作废 cache 中的数据,从而通过 cache 读取数据时 cache 会从内存取数据,所以 cpu 执行步骤 6 读取数据时,获取到的是从内存更新后的数据;
4. cache操作举例
4.1 外设数据 dma 传输
例如,在某顶盒平台中,内存加解密在单独的安全芯片中进行,安全芯片访问的数据通过 dma 进行传输操作。
因此,在进行内存加解密前,需要 flush d-cache 操作将数据同步到到内存中供安全芯片访问;
加解密完成后需要执行invalidate d-cache操作,以确保cpu访问的数据是安全芯片加解密的结果,而不是cache之前保存的数据;
dma进行数据加解密的示例代码:
void mem_dma_desc( unsigned long mode, unsigned long srcaddr, /* input data addr */ unsigned long destaddr, /* output data addr */ unsigned long slot, unsigned long size) /* dma data size */ { ...prepare for dma encryption/decryption operation... /* flush data in srcaddr from d-cache to memory to ensure dma device get the correct data */ flush_d_cache(srcaddr, size); ...do dma operation, output will be redirect to destaddr... /* invalidate d-cache to ensure fetch data from memory instead of cached data in d-cache */ invalidate_d_cache(destaddr, size); return; } 4.2 外设 flash 的 i/o
某平台的 nand flash 的控制器也支持 dma 读取的方式。在数据向 nand flash 写入数据时需要先 flash dcache 确保dma 操作的数据是真实要写入的数据,而不是内存中已经过期的数据;
从nand flash 读取数据后需要 invalidate dcache,使 cache 中的数据失效,从而确保 cpu 读取的是内存数据,而不是上一次访问时缓存的结果。
nand flash 通过 dma 方式读取数据的示例代码:
static int nand_dma_read( struct nand_dev *nand, uint64_t addr, /* read addr */ void *buf, /* output buffer */ size_t len){ int ret; ...prepare for nand flash read and device dma transfer... /* flush dma descriptor for nand flash read operation */ flush_d_cache(descs, ndescs * sizeof(*descs)); /* nand flash dma read operation */ ret = nand_dma_run(nand, (uintptr_t)descs); /* invalidate read output buffer to ensure fetch data from memory instead of cached data in d-cache */ invalidate_d_cache(buf, len); ...other operations... return ret;} 除了 nand flash 之外,很多硬盘也支持 dma 方式读取。
4.3 i-cache 和 d-cache 的转换
通常 cache 分为 i-cache 和 d-cache,取指令时访问 i-cache,读写数据时访问 d-cache。
但在代码搬运时,外设上存放的指令会被当作数据进行处理。
例如一段代码保存在外设(如nand flash或硬盘)上,cpu想执行这段代码,需要先将这段代码作为数据复制到内存再将这段代码作为指令执行。
由于写入数据和读取指令分别通过 d-cache 和 i-cache,所以需要同步 d-cache 和 i-cache,即复制后需要先将 d-cache 写回到内存,而且还需要作废当前的 i-cache 以确保执行的是 memory 内更新的代码,而不是 i-cache 中缓存的数据,如图四所示:
图四、cpu复制代码后执行
cpu复制代码后执行的示例代码:
红外遥控厂商:湖南融和微电子有限公司简介
“Matter开发流程”在线課堂-开发环境设置指南和应用示例
移动通信网络云计算的设计和实现
MAX941, MAX942, MAX944 低功耗、3V/
消息称荣耀已迁址,采用高通芯片的荣耀 5G 手机正在研发中
什么是 Cache? Cache读写原理
sE Electronics的产品, RF防反射隔声罩获美国专利
NS4248 3W双声道D类音频功放概述、特性及应用
钛米获2亿B轮融资,助力特种医疗服务机器人的发展
智能自动重合闸漏电保护器的优势
中兴通讯提出基于TITAN平台的AO重构方案
iphone8什么时候上市多少钱?iPhone8线下已开始预订!32G价格6288起,要不要考虑一下华为mate10?
三星s8什么时候上市?三星s8最新消息:堆料狂魔?三星S8的造价成本,比肩小米6的售价!
中国电信实测5G通信性能,荣耀手机整体领先
魅蓝E2最新消息:魅蓝E2真机配置曝光,隐藏式闪光灯,全新处理器售价或1699!
“安芯”植入RFID技术,助力产业数字化升级
Grace设计是为了填补英伟达人工智能服务器中CPU的空缺
三星Note10 Lite渲染图曝光采用了Infinity-O屏幕设计四周边框较窄
中小企业布局智能制造 NIP与机械云助力串连端到云
广和通推出区块链模组,加速碳中和进程