转自:http://blog.csdn.net/u011461299/article/details/10199989

版权声明:本文为博主原创文章,未经博主允许不得转载。

在驱动程序的设计中,我们可能会用到flush_cache_all将ARM cache的内容刷新到RAM,这是因为ARM Linux中cache一般会被设定为write back的。而通常象DMA是访问不了cache,所以如果我们需要启动DMA将RAM中的内容写到Flash中或LCD framebuffer,那么我们就需要调用flush_cache_all将cache中最新的内容刷新到RAM中。如果不这样做在LCD中可能会出现花屏。本文主要分析在ARM平台上到底如何实现的。

1.1                   flush_cache_all在ARM Linux中的实现

在include/asm-arm/cacheflush.h中:

#define flush_cache_all()             __cpuc_flush_kern_all()

#define __cpuc_flush_kern_all            cpu_cache.flush_kern_all

在setup_processor():

list = lookup_processor_type(processor_id);

//根据processor id找到对应ARM CPU(常见的如ARM926)相关的信息,存在list中。如果想把事情彻底搞清楚,必然要问processor_id是怎么来。它是在Linux Kernel启动时候从ARM chip中读出来。如果以后有机会大家一起讨论ARM Linux的启动全过程,可以详细分析。

cpu_cache = *list->cache;

而lookup_processor_type定义在arch/arm/kernel/head-comman.S中:相应的assembler code如下:

.type __lookup_processor_type, %function

__lookup_processor_type:

adr   r3, 3f

ldmda       r3, {r5 - r7}

sub  r3, r3, r7                      @ get offset between virt&phys

add  r5, r5, r3                      @ convert virt addresses to

add  r6, r6, r3                      @ physical address space

1:         ldmia        r5, {r3, r4}                    @ value, mask

and  r4, r4, r9                      @ mask wanted bits

teq    r3, r4

beq  2f

add  r5, r5, #PROC_INFO_SZ            @ sizeof(proc_info_list)

cmp r5, r6

blo    1b

mov  r5, #0                                    @ unknown processor

2:         mov  pc, lr

/*

* This provides a C-API version of the above function.

*/

ENTRY(lookup_processor_type)

stmfd        sp!, {r4 - r7, r9, lr}

mov  r9, r0

bl      __lookup_processor_type

mov  r0, r5

ldmfd        sp!, {r4 - r7, r9, pc}

/*

* Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for

* more information about the __proc_info and __arch_info structures.

*/

.long          __proc_info_begin

.long          __proc_info_end

3:         .long          .

.long          __arch_info_begin

.long          __arch_info_end

它其实就是到__proc_info_begin开始的section中去找到对应当前SOC中用的CPU Cache相关的operation list

再由arch/arm/kernel/vmlinux.lds.S可以__proc_info_begin就是section *(.proc.info.init)的开始地址。

__proc_info_begin = .;

*(.proc.info.init)

__proc_info_end = .;

而我们知道我们所用是ARM926,所以其定义在arch/arm/mm/proc-arm926.S:

.section ".proc.info.init", #alloc, #execinstr

.type       __arm926_proc_info,#object

__arm926_proc_info:

.long       0x41069260                  @ ARM926EJ-S (v5TEJ)

.long       0xff0ffff0

.long   PMD_TYPE_SECT | \

PMD_SECT_BUFFERABLE | \

PMD_SECT_CACHEABLE | \

PMD_BIT4 | \

PMD_SECT_AP_WRITE | \

PMD_SECT_AP_READ

.long   PMD_TYPE_SECT | \

PMD_BIT4 | \

PMD_SECT_AP_WRITE | \

PMD_SECT_AP_READ

b     __arm926_setup

.long       cpu_arch_name

.long       cpu_elf_name

.long         HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA

.long       cpu_arm926_name

.long       arm926_processor_functions

.long       v4wbi_tlb_fns

.long       v4wb_user_fns

.long       arm926_cache_fns

.size       __arm926_proc_info, . - __arm926_proc_info

arm926_cache_fns定义在同一个文件中,如下:

ENTRY(arm926_cache_fns)

.long       arm926_flush_kern_cache_all

.long       arm926_flush_user_cache_all

.long       arm926_flush_user_cache_range

.long       arm926_coherent_kern_range

.long       arm926_coherent_user_range

.long       arm926_flush_kern_dcache_page

.long       arm926_dma_inv_range

.long       arm926_dma_clean_range

.long       arm926_dma_flush_range

它所对应的struct的定义:(include/asm-arm/cacheflush.h)

struct cpu_cache_fns {

void (*flush_kern_all)(void);

void (*flush_user_all)(void);

void (*flush_user_range)(unsigned long, unsigned long, unsigned int);

void (*coherent_kern_range)(unsigned long, unsigned long);

void (*coherent_user_range)(unsigned long, unsigned long);

void (*flush_kern_dcache_page)(void *);

void (*dma_inv_range)(const void *, const void *);

void (*dma_clean_range)(const void *, const void *);

void (*dma_flush_range)(const void *, const void *);

};

所以其实flush_cache_all 在我们的项目中就是arm926_flush_kern_cache_all:其实现在同一个文件中:

/*

*   flush_kern_cache_all()

*  Clean and invalidate the entire cache.

*/

ENTRY(arm926_flush_kern_cache_all)

mov r2, #VM_EXEC

mov ip, #0

__flush_whole_cache:

#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH

mcr  p15, 0, ip, c7, c6, 0              @ invalidate D cache

#else

1:      mrc  p15, 0, r15, c7, c14, 3   @ test,clean,invalidate

bne  1b

#endif

tst   r2, #VM_EXEC

mcrne     p15, 0, ip, c7, c5, 0              @ invalidate I cache

mcrne     p15, 0, ip, c7, c10, 4            @ drain WB

mov pc, lr

最后我们它不仅仅flush 所有的cache(包括ICache和DCache),也flush了Write Buffer。

Linux Kernel之flush_cache_all在ARM平台下是如何实现的【转】的更多相关文章

  1. [转]ARM平台下独占访问指令LDREX和STREX

    参考:ARM平台下独占访问指令LDREX和STREX的原理与使用详解 全文转载如下: 为了实现线程间同步,一般都要在执行关键代码段之前加互斥(Mutex)锁,且在执行完关键代码段之后解锁.为了实现所谓 ...

  2. 4G通信模块在ARM平台下的应用

    4G模块是连接物与物的重要载体,是终端设备接入物联网的核心部件之一.随着4G的普及,许多新兴市场对4G通信模块的需求都在日益扩大,那么在ARM平台的嵌入式设备上如何快速的应用4G模块呢? 4G通信模块 ...

  3. 4G 通信模块在ARM 平台下的应用

    收藏 评论(0) 分享到 微博 QQ 微信 LinkedIn 4G模块是连接物与物的重要载体,是终端设备接入物联网的核心部件之一,随着4G的普及,许多新兴市场对4G通信模块的需求都在日益扩大,那么在A ...

  4. NDK编程的一个坑—Arm平台下的类型转换

    最近在做DNN定点化相关的工作,DNN定点化就是把float表示的模型压缩成char表示,虽然会损失精度,但是由于DNN训练的模型值比较接近且范围较小,实际上带来的性能损失非常小.DNN定点化的好处是 ...

  5. Mplayer ARM平台下交叉编译

    下载MPlayer http://www.mplayerhq.hu/design7/dload.html 编译环境 系统 : ubuntu 11.04 交叉编译器版本 : Sourcery G++ L ...

  6. ARM 平台下的 SSHD 配置

    sshd_config 文件中 允许 root 用户登录 PermitRootLogin yes 配置为内部的 sftp Subsystem sftp internal-sftp key 配置 ssh ...

  7. Linux kernel的中断子系统之(六):ARM中断处理过程

    返回目录:<ARM-Linux中断系统>. 总结:二中断处理经过两种模式:IRQ模式和SVC模式,这两种模式都有自己的stack,同时涉及到异常向量表中的中断向量. 三ARM处理器在感知到 ...

  8. Linux Kernel代码艺术——系统调用宏定义

    我们习惯在SI(Source Insight)中阅读Linux内核,SI会建立符号表数据库,能非常方便地跳转到变量.宏.函数等的定义处.但在处理系统调用的函数时,却会遇到一些麻烦:我们知道系统调用函数 ...

  9. Linux Kernel空指针引用本地拒绝服务漏洞(CVE-2013-5634)

    漏洞版本: Linux kernel 漏洞描述: BUGTRAQ ID: 61995 CVE(CAN) ID: CVE-2013-5634 Linux Kernel是Linux操作系统的内核. 适用于 ...

随机推荐

  1. MySQL: 详细的sql语句

    1添 1.1[插入单行] insert [into] <表名> (列名) values (列值)例:insert into Strdents (姓名,性别,出生日期) values ('开 ...

  2. delegate and event

    事件是特殊的委托 委托:第一个方法注册用“=”,是赋值语法,因为要进行实例化,第二个方法注册则用的是“+=”   修饰符应该public的时候public,应该private的时候private 事件 ...

  3. 微信公众平台开发(68)苹果IMEI查询

    微信公众平台开发 苹果IMEI查询 苹果序列号查询 iPhone/iPad/iPod/Mac 作者:方倍工作室 地址:http://www.cnblogs.com/txw1958/p/weixin69 ...

  4. Android 脚本替换PackageName

    原文简书地址:http://www.jianshu.com/p/dca9c323c686 1 前言 平时如果想要替换包名一般是在AS中右键Rename进行操作.但是如果遇到一份代码希望导出几种不同的包 ...

  5. MPI简介

    什么是MPI: MPI是一个库,而不是一门语言.但是按照并行语言的分类,可以把FORTRAN+MPI或者C+MPI看作是一种在原来串行语言基础上扩展后得到的并行语言.MPI库可以被FORTRAN77/ ...

  6. [BS] 小知识点总结-04

    1. ios新知识学习思路: 在开发过程中如果遇到某种新需求以前从未做过,例如改变textField的Placeholder颜色,有如下思路和途径: 1.1 在Storyboard/Xib辅助编辑器A ...

  7. Android之绚丽的图片游览效果--有点像W7效果,透明的倒影,层叠的图片,渐变的颜色透明度

    这里转载一个牛人的博客:http://www.cnblogs.com/tankaixiong/archive/2011/02/24/1964340.html 下面,是我参照他的博客实现的一个效果图.这 ...

  8. [RGEOS]支持栅格数据读取和显示

    SharpMap真的很强大,这里通过改造GdalRasterLayer类实现了在RGeos项目中支持栅格图像的读取和显示,同时支持影像的无级缩放. GdalRasterLayer通过读取FWTools ...

  9. iOS SQLite 增删改查的封装(关系型)

    在工程里导入libsqlite3.tbd库(Xcode 7) #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder &l ...

  10. Protostuff序列化

    前言: Java序列化是Java技术体系当中的一个重要议题,序列化的意义在于信息的交换和存储,通常会和io.持久化.rmi技术有关(eg:一些orm框架会要求持久化的对象类型实现Serializabl ...