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

2020-01-20来源: eefocus关键字: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


      //以下三个循环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)

关键字:armv8  aarch64  linux内核  flush_dcache_all函数 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic486244.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:关于ARMv8指令的几个问题
下一篇:ARMv8 Linux内核head.S源码分析

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

ARMv7体系结构学习笔记(一)
本轮学习过程主要集中在ARM NEON技术的学习,主要包括指令的学习、编程技巧的总结。ARM NEON 技术是ARMv7体系结构的可选组件。NEON是针对高级媒体和信号处理应用程序以及嵌入式处理器64/128位混合SIMD技术,它是作为ARM内核的一部分实现的,但有自己的执行管道和寄存器组,该寄存器组不同于ARM核心寄存器组。NEON支持整数、定点和单精度浮点SIMD运算。这些指令在ARM和Thumb-2中都可用。NEON 扩展寄存器组:--- 16-128bit 四字寄存器Q0~Q15--- 32-64bit 双字寄存器D0~D31许多NEON数据处理指令可具有正常指令、长指令、宽指令、窄指令和饱和指令变体
发表于 2020-02-04
ARMv7用户层发生指令异常的处理流程
1、用户层发生指令异常的处理流程?用户层程序正在执行时,遇到未定义的指令(ARM不是别的指令)或者SWI软件中断指令(产生系统调用),就会产生异常,这里以未定义指令异常为例进行说明:一旦出现未定义指令异常,CPU会自动做如下操作:(1)未定义模式(ARM其中运行模式的一种)下对应的lr(即R14)寄存器保存当前发生异常的指令下一条指令的地址。例如,在用户态有A B C 三条指令,指令A发生未定义指令异常,则指令B的地址就会由CPU保存到未定义模式下的lr寄存器中,用于异常返回。(2)CPU修改CPSR寄存器,进入未定义模式:CPSR[4:0]=0b11011   /*将CPSR的低五位置位11011,正好对应未定
发表于 2020-01-20
ARMv8 Linux内核head.S源码分析
ARMv8Linux内核head.S主要工作内容:1、 从el2特权级退回到el12、 确认处理器类型3、 计算内核镜像的起始物理地址及物理地址与虚拟地址之间的偏移4、 验证设备树的地址是否有效5、 创建页表,用于启动内核6、 设置CPU(cpu_setup),用于使能MMU7、 使能MMU8、 交换数据段9、 跳转到start_kernel函数继续运行。/* *Low-level CPU initialisation *Based on arch/arm/kernel/head.S * *Copyright (C) 1994-2002 Russell King 
发表于 2020-01-20
关于ARMv8指令的几个问题
NOTE:以下内容只针对ARMv8。问题一:ARMv8 branch指令格式及用法(《ARMv8ISA overview》中 page 25有相关叙述):1、无条件分支+立即数:直接跳转到某地址,不能跳转到寄存器指令有两个:”b label”  ”bl label”。在编译过程,编译器会将label翻译成立即数。举例:编写汇编代码如下main:     label:  nop      b label      ret编译并且反汇编后:0000000000400510 <main>:label(): 
发表于 2020-01-20
从编译器源码中提取ARMv8的指令编码
问题1:提取ARMv8的指令编码答:ARMv8指令的opcode可以在支持ARMv8的编译器binutils中找到,该工具能在网上找到,见参考资料[1],或者在[1]中搜索aarch64_opcode_table。为了说明指令编码细节,现将网页中部分内容摘录如下:1208 struct aarch64_opcode aarch64_opcode_table[] =1209 {1210  /* Add/subtract (with carry).  */1211  {"adc", 0x1a000000, 0x7fe0fc00, addsub_carry, 0, CORE, OP3
发表于 2020-01-20
从编译器源码中提取ARMv8的指令编码
交叉编译Python-2.7.13到ARM(aarch32)平台
-p1 < ../python2_7_13_for_arm/Python-2.7.13-xcompile.patch我也把编译过程放到脚本,也分为三个:配置 mk1_conf.sh1 #!/bin/bash2 export PATH=/home/pengdonglin/src/qemu/aarch32/arm-2014.05/bin:$PATH3 ../Python-2.7.13/configure --prefix=`pwd` 4     --host=arm-none-linux-gnueabi 5     --build=x86_64
发表于 2020-02-09
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved