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
后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函数详细分析【转】
转自:http://blog.csdn.net/qianlong4526888/article/details/12062809 版权声明:本文为博主原创文章,未经博主允许不得转载. /* * __ ...
- 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系统中设置TextView的行间距(非行高)
Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...
- Android三种实现自定义ProgressBar的方式介绍
一.通过动画实现 定义res/anim/loading.xml如下: View Row Code<?xml version="1.0" encoding="UTF- ...
- spring注入成员对象
就是将对象注入到另外一个对象中.这个样例就是有一个学校类,学校类中有一个校长类,最后使用測试文件输出学校类中的信息. 代码结构 学校类 package com.test.SpringGetSet; p ...
- Android WindowManager的使用
经常,我们看到在桌面上可移动的悬浮窗,这种场景还是很多的, 像流量统计,桌面歌词等,安全软件的清理小部件 这种小部件主要是通过 WindowManager ; WindowManager.Layout ...
- LINQ的基本用法
1.var q =from c in db.Customers select c.ContactName; 这个语句只是一个声明或者一个描述,并没有真正把数据取出来,只有当你需要该数据的时候,它才会执 ...
- 国内优秀npm镜像
淘宝npm镜像 淘宝npm镜像:http://npm.taobao.org/ 1.临时使用 npm --registry https://registry.npm.taobao.org install ...
- ViewPager滑动特效实现
ewPager最常用于结合Fragment,这是一个方便的方式来供应和管理每个页面的生命周期. MainAcitivity的代码 import java.util.ArrayList; import ...
- javascript原型prototype的一个你不一定知道的理解
原型和原型链的故事 相关文章: 为什么原型继承很重要 先来看看一段小代码用以引入要讲的小故事. function Foo() {}; var f1 = new Foo(); Foo.prototype ...
- 【转】mysql数据库中实现内连接、左连接、右连接
[转]mysql数据库中实现内连接.左连接.右连接 内连接:把两个表中数据对应的数据查出来 外连接:以某个表为基础把对应数据查出来 首先创建数据库中的表,数据库代码如下: /* Navicat MyS ...
- Windows 2008 server R2安装.NET Framework4时提示“灾难性故障”解决
在安装行环境.NET Framework 4时无法安装,提示“灾难性故障”.服务器的操作系统是windows server 2008 R2. 查看系统日志时显示“无法安装 Windows 更新 &q ...