实战之 arm64 刷 cache

实战之 arm64 刷 cache

小问题

  1. arm64下如何使用指令将数据cache全部刷掉?
  2. 用户态是否可以刷cache

1. 前言

通常的我们说的刷cache可能包括了两类动作:

  1. clean: 将cache里面的新内容写入到ddr
  2. invalidate: 将cache里面的内容无效掉,即丢掉

虽然都说刷cache,实际可能是上面两类动作的一种或者组合
例如:如果刷指令cache,因为指令是只读的,直接invalidate即可。
如果刷数据cache,如果明确可以直接丢掉数据则可以直接使用invalidate;
通常的刷数据cache需要先clean再invalidate;
当然数据cache也可以只clean不invalidate

2. cache的结构

cpu0-cpu1-cpu2-cpu3-
level1IDIDIDID
level2cluster0-U---cluster1-U---
ddr缓存(l3)all-share-U-------
ddr--------
  • pou 到l2
  • poc 到l3

3. 刷cache有哪些指令

3.1 刷指令cache的指令

指令解释动作是否支持用户态执行
IC IALLUISInvalidate all to Point of Unification, Inner ShareableI
IC IALLUInvalidate all to Point of UnificationI
IC IVAU, XtInvalidate by virtual address to Point of UnificationI

3.2 刷数据cache的指令

指令解释动作是否支持用户态执行
DC IVAC, XtInvalidate by virtual address to Point of CoherencyI
DC ISW, XtInvalidate by set/wayI
DC CVAC, XtClean by virtual address to Point of CoherencyC
DC CSW, XtClean by set/wayC
DC CVAU, XtClean by virtual address to Point of UnificationC
DC CIVAC, XtClean and invalidate by virtual address to Point of CoherencyC&I
DC CISW, XtClean and invalidate by set/wayC&I

4. linux刷cache有哪些接口

4.1 刷指令cache的接口

  • __flush_icache_range(regs->pc, regs->pc + AARCH64_INSN_SIZE); — ic ivau
  • __flush_icache_all(); — ic ialluis

4.2 刷数据cache的接口

extern void __flush_dcache_area(void *addr, size_t len); —dc civac
extern void __inval_dcache_area(void *addr, size_t len); —dc ivac
extern void __clean_dcache_area_poc(void *addr, size_t len); --dc cvac
extern void __clean_dcache_area_pop(void *addr, size_t len); --dc ARM64_HAS_DCPOP
extern void __clean_dcache_area_pou(void *addr, size_t len); --dc cvau

5. 如何全局的刷cache

从上面的接口可以看出,刷指令cache存在全局的指令,但数据cache没有全局的指令。
最简单的的如果需要全局刷数据cache则使用DC CISW, Xt将所有的set/way刷一遍

其中芯片各级cache有多少way是直接描述的
再根据cache总大小可以计算出有多少set

如A72 L1-I
48KB 3-way set-associative instruction cache. Fixed line length of 64 bytes.
则set = 481024 / 64 / 3 == 256
如L1-D 32KB 2-way set-associative data cache.Fixed line length of 64 bytes
则set = 32
1024 / 64 / 2 == 256
如L2 1M
• Configurable L2 cache size of 512KB, 1MB, 2MB and 4MB.
• Fixed line length of 64 bytes.
• Physically indexed and tagged cache.
• 16-way set-associative cache structure.
• Banked pipeline structures.
• Inclusion property with L1 data caches.
则set = 110241024 / 64 / 16 == 1024

+static void flush_cache_internal(unsigned int way_shift, unsigned int way_max,
+            unsigned int set_shift, unsigned int set_max, unsigned int level)
+{
+#define FLEVEL_SHIFT 1
+    unsigned long set, way;
+    unsigned long setway;
+
+    for (way = 0; way <= way_max; way++) {
+        for (set = 0; set <= set_max; set++) {
+            setway = way << way_shift | set << set_shift | level << FLEVEL_SHIFT;
+            //pr_info("setway=%lx, way=%ld, set=%ld, l=%d\n", setway, way, set, level);
+            asm volatile("dc cisw, %0" : : "r" (setway) : "memory");
+        }
+    }
+}
+
+static void flush_l1dl2d_all(void)
+{
+#define FL1D_LEVEL_V 0
+#define FL1D_WAY_SHIFT 31
+#define FL1D_WAY_MAX 1
+#define FL1D_SET_SHIFT 6
+#define FL1D_SET_MAX 255
+
+#define FL2D_LEVEL_V 1
+#define FL2D_WAY_SHIFT 28
+#define FL2D_WAY_MAX 15
+#define FL2D_SET_SHIFT 6
+#define FL2D_SET_MAX 1023
+    unsigned long start, end;
+    start = sched_clock();
+    flush_cache_internal(FL1D_WAY_SHIFT, FL1D_WAY_MAX, FL1D_SET_SHIFT, FL1D_SET_MAX, FL1D_LEVEL_V);
+    flush_cache_internal(FL2D_WAY_SHIFT, FL2D_WAY_MAX, FL2D_SET_SHIFT, FL2D_SET_MAX, FL2D_LEVEL_V);
+    end = sched_clock();
+    pr_info("cache flush start=%ld, end=%ld, delta=%ld\n", start, end, end - start);
+}

6. 什么时候需要刷cache

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值