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)
如果你对此有疑问,欢迎留言讨论。
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( ...
- Linux内核OOM机制的详细分析(转)
Linux 内核 有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了 防止内存耗尽而内核会把该进程杀掉.典 ...
- Linux内核中SPI总线驱动分析
本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...
- Linux内核中kzalloc函数详解
**************************************************************************************************** ...
- Linux内核OOM机制的详细分析【转】
本文转载自:http://blog.csdn.net/liukuan73/article/details/43238623 Linux内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没 ...
- Linux内核TCP MSS机制详细分析
前言 上周Linux内核修复了4个CVE漏洞[1],其中的CVE-2019-11477感觉是一个很厉害的Dos漏洞,不过因为有其他事打断,所以进展的速度比较慢,这期间网上已经有相关的分析文章了.[2] ...
- Linux内核中的Workqueue机制分析
1. 什么是workqueue Linux中的workqueue(工作队列)主要是为了简化在内核创建线程而设计的.通过相应的工作队列接口,可以使开发人员只关心与特定功能相关的处理流程,而不必关心内核线 ...
- Linux内核OOM机制的详细分析
Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉.典型的 ...
- Linux内核中container_of函数详解
http://www.linuxidc.com/Linux/2016-08/134481.htm
随机推荐
- Android 使用PullToRefresh实现下拉刷新和上拉加载(ExpandableListView)
PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的Vie ...
- tomecat 配置修改 及启动配置
a.如果tomcat是以bat方式启动的,则如下设置: 修改TOMCAT_HOME/bin/catalina.sh 在“echo "Using CATALINA_BASE: $CATALIN ...
- MySQL 事件跟踪器 , MySQL 无须重启服务 跟踪 SQL , 也无须配置日志
第一步 创建以下两个 日志表 按 Ctrl+C 复制代码 按 Ctrl+C 复制代码 CREATE TABLE `general_log` ( `event_time` timestamp NOT N ...
- [转][C++ 11]override and final - write clean and maintainable C++ code
原文: http://arne-mertz.de/2015/12/modern-c-features-override-and-final/ Today I write about a pair of ...
- html 全选或全不选小案例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- mac gcc 编译错误 基础问题
mac gcc Undefined symbols for architecture x86_64 "std::__1: // Undefined symbols for architec ...
- ios提示框,自动消失
-(void)click { NSString *showMsg = @"点击我,开始提示"; int width = showMsg.length * 20; UIWindow ...
- Android之Handler,举例说明如何更新UI
方法一:(java习惯,在android不推荐使用) 刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题 new Thread( new Runnable() { ...
- 学习OpenCV——OpenMP
转自:http://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html openMP的一点使用经验 最近在看多核编程.简单来说,由 ...
- 最长上升子序列的变形(N*log(N))hdu5256
序列变换 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...