【问题标题】:How to flush cache line in aarch64如何在 aarch64 中刷新缓存行
【发布时间】:2018-10-30 02:10:35
【问题描述】:

如何在用户空间代码中刷新 aarch64 上的缓存行?就像在 x86 上一样,我们可以使用以下 lib 调用:

_mm_clflush(&array);

我尝试了以下代码:

void flush(void)
{
    asm volatile ( "MCR p15, 0, =0x0,c7, c6, 0\n");
    return;
}

但是GCC有编译错误:

Error: unknown mnemonic `mcr' -- `mcr p15,0,=0x0,c7,c6,0'

谢谢。


@Peter 的评论更新: 我用以下代码尝试了__builtin___clear_cache

int tt = 0;
unsigned long *ptr;

tt++;
TIMESTAMP(ts2);
printf("cycle: %lu. %d\n", ts2-ts1, tt);

ptr = &tt;
__builtin___clear_cache(ptr, ptr+128);
TIMESTAMP(ts1);
tt++;
TIMESTAMP(ts2);
printf("cycle: %lu. %d\n", ts2-ts1, tt);

结果似乎没有显示我们已成功将数据从数据缓存中逐出:

cycle: 5. 1
cycle: 0. 2

我查看了反汇编,并引用了the AARCH64 instruction manual。好像内置函数清理了缓存吧?

0000000000400788 <__clear_cache>:
  400788:       14000002        b       400790 <__aarch64_sync_cache_range>
  40078c:       00000000        .inst   0x00000000 ; undefined

0000000000400790 <__aarch64_sync_cache_range>:
  400790:       b0000083        adrp    x3, 411000 <_GLOBAL_OFFSET_TABLE_+0x28>
  400794:       b9404462        ldr     w2, [x3,#68]
  400798:       35000082        cbnz    w2, 4007a8 <__aarch64_sync_cache_range+0x18>
  40079c:       d53b0024        mrs     x4, ctr_el0
  4007a0:       2a0403e2        mov     w2, w4
  4007a4:       b9004464        str     w4, [x3,#68]
  4007a8:       d3504c44        ubfx    x4, x2, #16, #4
  4007ac:       52800083        mov     w3, #0x4                        // #4
  4007b0:       12000c45        and     w5, w2, #0xf
  4007b4:       1ac42064        lsl     w4, w3, w4
  4007b8:       51000482        sub     w2, w4, #0x1
  4007bc:       1ac52063        lsl     w3, w3, w5
  4007c0:       8a220002        bic     x2, x0, x2
  4007c4:       93407c84        sxtw    x4, w4
  4007c8:       eb01005f        cmp     x2, x1
  4007cc:       540000a2        b.cs    4007e0 <__aarch64_sync_cache_range+0x50>
  4007d0:       d50b7b22        dc      cvau, x2
  4007d4:       8b040042        add     x2, x2, x4
  4007d8:       eb02003f        cmp     x1, x2
  4007dc:       54ffffa8        b.hi    4007d0 <__aarch64_sync_cache_range+0x40>
  4007e0:       d5033b9f        dsb     ish
  4007e4:       51000462        sub     w2, w3, #0x1
  4007e8:       93407c63        sxtw    x3, w3
  4007ec:       8a220000        bic     x0, x0, x2
  4007f0:       eb00003f        cmp     x1, x0
  4007f4:       540000a9        b.ls    400808 <__aarch64_sync_cache_range+0x78>
  4007f8:       d50b7520        ic      ivau, x0
  4007fc:       8b030000        add     x0, x0, x3
  400800:       eb00003f        cmp     x1, x0
  400804:       54ffffa8        b.hi    4007f8 <__aarch64_sync_cache_range+0x68>
  400808:       d5033b9f        dsb     ish
  40080c:       d5033fdf        isb
  400810:       d65f03c0        ret
  400814:       00000000        .inst   0x00000000 ; undefined

【问题讨论】:

  • 您要同步数据/指令缓存吗? GNU C 的__builtin__clear_cache 会这样做:How does __builtin___clear_cache work? 或者你真的需要从缓存中驱逐数据的东西吗? __builtin__clear_cache不一定这样做,尽管名称。
  • 我应该包含什么头文件才能使用__buildin__clear_cache?我想从 aarm64 上的缓存中清除数据。谢谢。
  • 参见ARMv8 Reference Manual,从 C5-409 页开始。注意EL0访问可以关闭,见this answer of mine
  • 没有头文件。这就是内置函数的全部意义所在。它是预定义的。 gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html。另请注意,您有一个错字,它是builtin 而不是buildin。检查你得到什么asm;就像我说的那样,它实际上可能不会从数据缓存中逐出数据,如果它可以在不这样做的情况下将其同步到指令缓存。
  • 谢谢@PeterCordes。我用你提到的内置更新。使用手册好像清除了缓存,但是结果并没有显示清除缓存的效果。

标签: caching cpu-architecture arm64


【解决方案1】:


1. "MCR p15, 0, =0x0,c7, c6, 0\n" 是Aarch32指令


2.正如@Peter上面提到的'flush'(或ARM TRM术语中的'clean')将数据从缓存复制到内存中,但缓存副本仍然有效。简单来说,你的__builtin___clear_cache 测试是一团糟。


3.“无效”从缓存中删除数据并确保数据从内存中读出。 (不过有一个问题,在无效数据之后可能会预取回缓存。因此,即使无效,您的测试也可能是一团糟)。


4. 检查 ARM TRM 是否有 'Clean by VA' 指令,它们中的大部分/全部都可以在用户空间之外执行。请注意,访问可能会被操作系统禁用/捕获,在这种情况下,您的应用会产生故障并可能会被操作系统终止。

PS:顺便说一句,你试图通过刷新来存档什么?

【讨论】:

    猜你喜欢
    • 2021-02-05
    • 2018-11-07
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    相关资源
    最近更新 更多