armv8(aarch64)linux内核中flush_dcache_all函数详细分析

armv8(aarch64)linux内核中flush_dcache_all函数详细分析



/*

 *  __flush_dcache_all()

*  Flush the wholeD-cache.

 * Corrupted registers: x0-x7, x9-x11

 */

ENTRY(__flush_dcache_all)

//保证之前的访存指令的顺序

    dsb sy           

 

      //读cache level id register

    mrs x0, clidr_el1           // read clidr

 

      //取bits[26:24](Level of Coherency for the cache hierarchy.)

//需要遵循cache一致性的cache层级(例如有3级cache,但2级需要做一致性)

    and x3, x0, #0x7000000      // extract loc from clidr

      //逻辑右移23位,把bits[26:24]放到bits[2:0]

    lsr x3, x3, #23         // left align loc bit field

 

      //如果需要做cache一致性的层级为0,则不需要flush,跳转到finished标记处。

    cbz x3, finished            // if loc is 0, then no need toclean

 

      //x10存放cache级,从level0 cache开始做flush

      //以下三个循环loop3set/wayx9),

//loop2indexx7),loop1cache level(x10)

    mov x10, #0             // start clean at cache level 0

loop1:

//x10+2后右移一位正好等于1,再加上x10本身正好等于3

      //每执行一次loop1,x2+3*执行次数,目的在于把x0(clidr_el1)右移3位,

//取下一个cache的ctype type fields字段,clidr_el1的格式见《ARMv8 ARM》

    add x2, x10, x10, lsr #1        /

      //x0逻辑右移x2位,给x1,提取cache类型放到x1中,x0中存放:clidr_el1

    lsr x1, x0, x2         

 

      //掩掉高位,只取当前cache类型

    and x1, x1, #7 

      /* 判断当前cache是什么类型:

* 000  No cache.

* 001  Instruction cache only.

* 010  Data cache only.

* 011  Separate instruction and data caches.

* 100  Unified cache.

*/

      //小于2说明data cache不存在或者只有icache,

//跳转skip执行,大于等于2继续执行

    cmp x1, #2             

    b.lt   skip               

     

/*

 *  Save/disableand restore interrupts.

 * .macro save_and_disable_irqs, olddaif

 * mrs \olddaif,daif                                                                                                                                                      

 * disable_irq

 * .endm

*/

      //保存daif到x9寄存器中,关闭中断

    save_and_disable_irqs x9        // make CSSELR and CCSIDR access atomic

      //选择当前cache级进行操作,csselr_el1寄存器bit[3:1]选择要操作的cache级

      //第一次执行时x10=0,选择level 0级cache

    msr csselr_el1,x10        

      //isb用于同步新的cs-s-r和csidr寄存器

    isb                

      //因为执行了“msr csselr_el1,x10”,所以要重新读取ccsidr_el1

    mrs x1, ccsidr_el1          // read the new ccsidr

 

    /*

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgjxpy.html