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

简介:

转自:http://blog.csdn.net/qianlong4526888/article/details/12062809

 

 

/*

 *  __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

      //以下三个循环loop3是set/way(x9),

//loop2是index(x7),loop1是cache 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用于同步新的cssr和csidr寄存器

    isb                

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

    mrs x1, ccsidr_el1          // read the new ccsidr

 

    /*

* .macro  restore_irqs, olddaif                                                                                                                                          

     * msrdaif, \olddaif

    . * endm

        */

    restore_irqs x9

      //x1存储ccsidr_el1内容,低三位是(Log2(Number of bytes in cache line)) – 4

      //加4后x2=(Log2(Numberof bytes in cache line))

    and x2, x1, #7          // extract the length of the cachelines

    add x2, x2, #4          // add 4 (line length offset)

    mov x4, #0x3ff

      //逻辑右移3位,提取bits[12:3](Associativityof cache) – 1,

      //x4存储cache的way数

    and x4, x4, x1, lsr #3     // find maximum number on the way size

      //计算x4前面0的个数,存到x5

    clz x5, x4              // find bit position of way sizeincrement

      //提取bits[27:13]位:(Number of sets in cache) - 1

    mov x7, #0x7fff

      //x7中存储cache中的set数

    and x7, x7, x1, lsr #13     // extract max number of the index size

loop2:

      //把x4值备份

    mov x9, x4              // create working copy of max waysize

loop3:

      //把需要操作哪个way存储到x6

    lsl x6, x9, x5

      //确定操作哪一级的哪个way(x10指定操作哪一级cache)

    orr x11, x10, x6            // factor way and cache number intox11

      //确定操作哪个set

    lsl x6, x7, x2

    orr x11, x11, x6            // factor index number into x11

      //x11中存储了哪一级cache(10),哪一路cache(x9),哪个set(x7)

    dc  cisw, x11           // clean & invalidate by set/way

      //way数-1

    subs   x9, x9, #1          // decrementthe way

    b.ge   loop3

    subs   x7, x7, #1          // decrementthe index

    b.ge   loop2

skip:

    add x10, x10, #2            // increment cache number,

//为什么加2不是1?见loop1标号处解释

    cmp x3, x10

    b.gt   loop1

finished:

    mov x10, #0             // swith back to cache level 0

    msr csselr_el1, x10         // select current cache level incsselr

    dsb sy

    isb

    ret

ENDPROC(__flush_dcache_all)

 

 

 如果你对此有疑问,欢迎留言讨论。













本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/5896363.html,如需转载请自行联系原作者


相关文章
|
14天前
|
Linux C语言
Linux内核队列queue.h
Linux内核队列queue.h
|
22天前
|
Linux
关于Linux目录访问函数总结
关于Linux目录访问函数总结
13 1
|
20小时前
|
算法 Linux Shell
【linux进程(二)】如何创建子进程?--fork函数深度剖析
【linux进程(二)】如何创建子进程?--fork函数深度剖析
|
7天前
|
算法 Linux 调度
深入理解Linux内核的进程调度机制
【4月更文挑战第17天】在多任务操作系统中,进程调度是核心功能之一,它决定了处理机资源的分配。本文旨在剖析Linux操作系统内核的进程调度机制,详细讨论其调度策略、调度算法及实现原理,并探讨了其对系统性能的影响。通过分析CFS(完全公平调度器)和实时调度策略,揭示了Linux如何在保证响应速度与公平性之间取得平衡。文章还将评估最新的调度技术趋势,如容器化和云计算环境下的调度优化。
|
12天前
|
算法 Linux 调度
深度解析:Linux内核的进程调度机制
【4月更文挑战第12天】 在多任务操作系统如Linux中,进程调度机制是系统的核心组成部分之一,它决定了处理器资源如何分配给多个竞争的进程。本文深入探讨了Linux内核中的进程调度策略和相关算法,包括其设计哲学、实现原理及对系统性能的影响。通过分析进程调度器的工作原理,我们能够理解操作系统如何平衡效率、公平性和响应性,进而优化系统表现和用户体验。
20 3
|
16天前
|
Linux 开发者
Linux文件编程(open read write close函数)
通过这些函数,开发者可以在Linux环境下进行文件的读取、写入和管理。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
84 4
|
19天前
|
负载均衡 算法 Linux
深度解析:Linux内核调度器的演变与优化策略
【4月更文挑战第5天】 在本文中,我们将深入探讨Linux操作系统的核心组成部分——内核调度器。文章将首先回顾Linux内核调度器的发展历程,从早期的简单轮转调度(Round Robin)到现代的完全公平调度器(Completely Fair Scheduler, CFS)。接着,分析当前CFS面临的挑战以及社区提出的各种优化方案,最后提出未来可能的发展趋势和研究方向。通过本文,读者将对Linux调度器的原理、实现及其优化有一个全面的认识。
|
19天前
|
Ubuntu Linux
Linux查看内核版本
在Linux系统中查看内核版本有多种方法:1) 使用`uname -r`命令直接显示版本号;2) 通过`cat /proc/version`查看内核详细信息;3) 利用`dmesg | grep Linux`显示内核版本行;4) 如果支持,使用`lsb_release -a`查看发行版及内核版本。
36 6
|
21天前
|
Prometheus 监控 数据可视化
linux分析方法与技巧
【4月更文挑战第3天】在Linux环境中,进行日志分析和系统性能分析的关键方法包括:使用`cat`, `less`, `tail`查看和过滤日志,`logrotate`管理日志文件,`rsyslog`或`syslog-ng`聚合日志,以及通过`top`, `mpstat`, `pidstat`, `free`, `iostat`, `netstat`, `strace`, `sar`, `dstat`等工具监控CPU、内存、磁盘I/O和网络。对于高级分析,可利用Brendan Gregg的性能工具,以及Grafana、Prometheus等可视化工具。
17 2
linux分析方法与技巧
|
22天前
|
Linux 内存技术
Linux内核读取spi-nor flash sn
Linux内核读取spi-nor flash sn
18 1