Chinaunix首页 | 论坛 | 博客

fx

  • 博客访问: 1347402
  • 博文数量: 115
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3964
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-02 14:36
文章分类
文章存档

2022年(2)

2019年(2)

2018年(10)

2017年(1)

2016年(50)

2015年(12)

2014年(9)

2013年(29)

分类: 嵌入式

2014-04-01 10:08:20

ARM中用于存储管理的系统控制协处理器CP15介绍:
    在基于arm的嵌入式系统中,存储系统通常是通过系统控制协处理器CP15来完成的。
    CP15可以包含16个32位的寄存器,其编号为0-15.实际上对于某些编号的寄存器可能对应有多个物理寄存器,在指令中
    指定特定的标志位来区分这些物理寄存器。该机制类似与arm中某些寄存器在不同的处理器模式下对应不同的物理寄存器。
    访问CP15寄存器的指令有下面两种:
        MCR:ARM寄存器到协处理器寄存器的数据传送指令。
        MRC: 协处理器到arm寄存器的数据传送指令。
        MCR和MRC指令只能在处理器模式是系统模式时执行。在用户模式下执行该指令会触发未定义指令的异常中断。

        MCR{} p15,0,,, {,}
        为协处理器将执行的操作的操作码对于CP15,永远为0,若不为0则该操作结果不可知
        作为源寄存器的arm寄存器,不能为PC。
        作为目标寄存器的协处理器,其编号位可能为c0-c15.
        附加的目标寄存器或者源操作数寄存器。用于区分同一个编号的不同物理寄存器。当指令中不需要提供附加信息时,将指定为C0,否则指令操作不可预知。
        提供附加信息,用于区别同一个编号的不同物理寄存器。若不需要附加信息,省略或指定其为0,否则指令操作结果不可预知。
        如指令: MCR p15,0,R4,C1,c0,0    该指令将arm寄存器r4中的数据传送到协处理器CP15中的C1中。操作码1和操作码2均为0。

        MRC{} p15,0,,,{,}
        为协处理器寄存器,存放第一个源操作数。其他的参考MCR指令。

    CP15中的寄存器C0:
        寄存器C0中存放的是ARM相关的一些标志符。这个寄存器是只读的。指令中的操作码2标志要读取的信息。
        0b000表示读取主标识符寄存器,0b001表示读取Cache类型标识符寄存器,其他编码未定义。
        主标识符提供处理器版本信息
        Cache标识符提供了关于Cache的信息:
            数据和指令cache是分开的还是独立的。
            cache的容量,块大小以及相联特性
            cache的类型是写通的还是写回的以及对于写回类型如何有效清除cache内容
            cache是否支持内容锁定。
        如 MRC p15,0,R0,C0,C0,0 为读取Cp15的主标识符寄存器内容到arm寄存器R0中 
            MRC p15,0,R0,C0,C0,1为读取cp15的Cache类型标识符寄存器到arm寄存器R0中。

   CP15中的寄存器C1:
        使用MRC/MCR 传输数据时, CRm和opcode2的值均为0
        禁止/使能MMU以及其他的与存储系统相关的功能
        配置存储系统以及ARM处理器中的相关部分的工作方式。
        例如读取C1值: MRC p15,0,R0,c1,0,0
ARM中存储管理单元MMU介绍:
    与MMU操作相关的寄存器
        C1中的某些位
        C2保存内存中的页表基地址
        C3设置域的访问控制属性
        C5内存访问失效状态指示
        C6内存访问失效时失效的地址
        C8控制与清除TLB内容相关的操作
        C10控制与锁定TLB内容相关的操作
    禁止使能MMU: CP15中的寄存器C1的为[0]用来控制禁止/使能MMU。0禁止,1使能
    使能MMU: mrc p15,0,r0,c1,0,0 (注意对C1操作是 CRm和opcode2均为0).
                    orr r0,#1
                    mcr p15,0,r0,c1,0,0
    使能MMU时存储访问过程
            当ARM处理器请求存储访问时,首先在TLB中查找虚拟地址。如果系统中的数据TLB和指令TLB是分开的,在取指令时。
            从指令TLB查找相应的虚拟地址,对于其他的内存访问操作,从数据TLB中查找相应的虚拟地址。如果该虚拟地址的地址变换条目不在TLB中,
            CPU从位于内存中的页表中查询对应于该虚拟地址的地址变换条目,并把相应的结果添加到TLB中,如果TLB已经满了,还需要根据一定的淘汰算法进行替换。这样
            当CPU下一次又需要该地址变换条目时,可以从TLB中直接得到,从而使地址变换的速度大大增加。
            当得到了需要的地址变换条目后,将进行以下的操作
                1:得到该虚拟地址对应的物理地址。
                2:根据条目中的C(cachable)控制位和B(bufferable)控制位决定是否缓存该内存访问的结果
                3:根据存取权限控制位和域访问控制位确定该内存访问是否被允许。若不被允许,CP15向ARM处理器报告存储访问终止。,
                4:对于不允许缓存的存储访问,使用 1 中得到的物理地址访问内存。对于允许缓存的存储访问,如果在Cache命中,则忽略物理地址。若没有命中,
                        则使用得到的物理地址访问内存,并把该数据块读取到Cache中。

    禁止MMU时的存储访问过程
            当禁止MMU时,是否支持chche和write buffer由各个具体芯片的设计确定。如果芯片规定当禁止MMU时禁止Cache和write buffer,则存储访问将不考虑C,B控制位
            如果芯片规定当禁止MMU时可以使能cache和write buffer,则数据访问时c=0,B=0,指令读取时,如果使用分开的TLB则C=1,如果使用统一的TLB则C=0。
            存储访问不进行权限控制,MMU也不会产生存储访问终止信号。
            所有物理地址和虚拟地址相等,即使用平板存储模式。
    禁止/使能MMU时应注意的问题
            在使能MMU之前,要在内存中建立页表,同时CP15中的各相关寄存器必须完成初始化。
            如果使用的不是平板存储模式,在禁止/使能MMU时,虚拟地址和物理地址的对应关系会发生改变,这时应该清除cache中的当前地址变换条目
            如果完成禁止/使能MMU的代码的物理地址和虚拟地址不同,则禁止/使能MMU时将造成很大麻烦,因此通常完成使能/禁止MMU的代码的物理地址和虚拟
                地址是相同的



MMU中地址变换过程
    MMU中采用两级页表实现地址映射
        一级页表中包含有以段为单位的地址变换条目或指向二级页表的指针。一级页表实现的地址映射粒度较大。
        二级页表中包含以大页和小页为单位的地址变换条目。其中,一种类型的二级页表还包含有以极小页为单位的地址变换条目。
        通常以段为单位的地址变化过程只需要一级页表。而以页为单位的地址变换过程还需要二级页表。

        这里简单介绍基于段的地址映射
            CP15的寄存器C2中存放的是内存中页表的基地址。其中为[31:14]为内存中页表的基地址,位[13:0]为0。因此一级页表的基地址必须是16Kb对齐的。(原因是一级页表
            中的一个条目通常映射的大小为1MB,则4G内存可分为2^12个1MB,即一级页表中有2^12个条目。因为每个条目大小为4字节。
            所以一级页表大小共有4x2^12个字节即16KB。)

            CP15的寄存器C2的[31:14]和虚拟地址的[31:20]结合为一个32位数的高30位,低两位为0.从而形成一个32位的索引值。
            使用该索引值从页表中找到一个4字节的条目,称为一级描述符。该条目中包含了段对应的物理基地址或二级页表基地址。
            还包含了缓存控制位,权限控制位等。
            当该条目中的[1:0]位为10时,表示该一级描述符为段描述符。段描述符定义了对应的1MB的虚拟存储空间的地址映射关系。
            为段描述符时,从中取出段对应的物理基地址,然后与虚拟地址的[19:0]位结合,形成32位的物理地址。
关于快表(TLB)的操作
    使无效快表的内容
        当内存中的页表内容改变,或者通过修改系统控制协处理器CP15的寄存器C2来使用新的页表时,TLB中的内容需要全部或者部分使无效。MMU提供了相关的硬件支持。
        系统控制协处理器CP15的寄存器C8就是用来控制清除TLB内容的相关操作的。它是一个只写的寄存器。
        MCR指令写该寄存器: MCR p15,0,,c8,,
        中为将要写入C8的数据。,的不同组合决定指令执行不同的操作。
        使无效快表指令格式:
            指令 opcode_2 CRm Rd 含义
            MCR p15,0,Rd,c8,c7,0 0b000 0b0111 0 使无效整个统一cache或使无效整个数据和指令cache
            MCR p15,0,Rd,c8,c7,1 0b001 0b0111 虚拟地址 使无效cache中的单个地址变换条目
            MCR p15,0,Rd,c8,c5,0 0b000 0b0101 0 使无效整个指令cache
            MCR p15,0,Rd,c8,c5,1 0b001 0b0101 虚拟地址 使无效指令cache中的单个地址变换条目
            MCR p15,0,Rd,c8,c6,0 0b000 0b0110 0 使无效整个数据cache
            MCR p15,0,Rd,c8,c6,1 0b001 0b0110 1 使无效数据cache中的单个地址变换条目。
        若系统使用统一的指令和数据cache时。2,4,6行中指令是相同的 1,3,5行中的指令功能是相同的。
    快表内容的锁定
        CP15中寄存器c10用于控制TLB内容的锁定。 
ARM中的存储访问失效:
    MMU中与存储访问失效相关的寄存器有两个:寄存器C5为失效状态寄存器,寄存器C6为失效地址寄存器。

高速缓冲存储器(cache)和写缓冲区(write buffer)
    通常ARM处理器的主频可以达到几百MHZ.而一般的主存储器用动态存储器,其存储周期仅为100ns左右。这样如果指令和数据都存放在
    主存储器中,主存储器的速度将会严重制约整个系统的性能。高速缓冲存储器(cache)和写缓冲区(write buffer)位于主存储器和CPU之间。主要用来提高存储系统的性能。
    高速缓冲存储器是全部用硬件来实现的,所以对程序员来说是透明的。Cache与主存储器之间以块为单位进行数据的交换。当CPU读取数据或指令时,
    它同时将读取到的数据或者指令保存到一个cache块中。

    这样当CPU第二次需要读取相同的数据时,他可以从相应的cache中得到相应的数据。因为cache的速度远远大于主存储器的速度,系统的正题性能就能得到很大的提高。实际上
    在程序中同城相邻的一段时间内CPU访问相同的数据的概率是很大的,这种规律称为时间局部性。时间局部性保证是系统采用cache后,通常性能都能得到很大的提高。
    不同的系统中,cache的块大小也是不同的。当CPU从主存读取地址n的数据时,会将地址为n,n+1,n+2...的数据也读到cache的一个块中。
    这样CPU需要访问后面的地址的数据时,它可以从cache中得到该数据,系统的

    性能得到提升。实际上,在程序中,cpu访问相邻的存储空间的数据的概率是很大的,这种规律称为空间局部性。
    空间局部性保证了系统采用cache后,通常性能会得到很大的提升。


    写缓冲区是由一些高速的存储器构成的。他主要用来优化向主存储器中的写入操作。当CPU进行向主存中的写入操作时,
    他首先将数据写到缓冲区中,由于写缓冲区的访问速度很快,这种写入操作的速度也很快。

    然后CPU就可以进行下面的操作。写缓冲区在适当的时候以较低的速度将数据写入主存储器中相应的位置

    通过引入cache和写缓冲区,存储系统的性能得到了很大的提高,但同时也带来了一些问题。比如由于数据将存在于系统中不同的物理位置,可能造成数据的不一致性。
    由于写缓冲区的有有话作用,可能有些写操作的执行顺序不是用户期望的顺序。从而造成操作错误。


cache的分类
    统一/独立的数据cache和指令cache

        使用独立的数据cache和指令cache,可以在同一个时钟周期中读取指令和数据,但需要保证指令和数据的一致性。
        写通cache和写回cache:
        当CPU更新了cache的内容时,要将结果写回到主存中,通常有两种方法:写通法和写回法。
        写回法是指CPU在执行写操作时,被写的数据只写入cache中,不写入主存中。仅当需要替换时,才把已经修改的cache块写回到主存中。     
        采用这种更新算法的cache块表中,一般有一个修改位,当一块中的任何一个单元被修改时,这一块的修改位被置1,否则保持0.在需要替换这一块时,
        如果对应的修改位为1,

        则必须先把这一块写到主存中去之后,才能掉入新的快来覆盖。如果对应的修改位为0,则不必把这一块写到主存中,只要用新掉入的块覆盖该块即可。

        写通法是指CPU在执行写操作时,必须把数据同时写入cache中和主存中。这样在cache的块表中就不需要修改位。当某一块需要替换时,
        也不必把这一块写回到主存中去,新掉入的快可以立即把这一块覆盖掉


    比较
        可靠新:
            写通法优于写回法。写通法能始终保持cache是主存的正确副本。

        与主存的通信量:
            由于写通法在每次写cache时,同时写主存,从而增加了写操作的开销。而写回法是把写主存的开销集中在当发生cache失效时,可能要一次性地写一个块到主存中。
        控制的复杂性:
            写通法比写回法简单,写通法在快表中不需要修改位。
        硬件实现的代价:
            写回法比写通法好。因为写通法中,每次写操作都要写主存,因此为了节省写主存所花费的时间。通常要采用一个高速小容量的缓冲存储器,把要写的数据和
            地址写到这个缓冲器中。在每次读主存中时,也要首先判断所读取的数据是否在这个缓冲器中。而写回法的硬件实现代价相对较低。

    读操作分配cache和写操作分配cache
        当进行数据写操作时,可能cache未命中。这时根据cache执行的操作的不同可以将cache分为两类:读操作分配cache和写操作分配cache。
        对于读操作分配cache,当进行数据写操作时,如果未命中,只是简单地将数据写入主存中。主要在数据读取时,才进行cache内容的预取。
        对于写操作分配cache,当进行数据写操作时,如果cache未命中,cache系统会进行cache内容预取,从主存中将相应的块读到cache中相应的位置,
            再进行写操作,把数据写入cache中。

        对于写通类型的cache,数据会同时被写入到主存中,对于写回类型的cache数据将会在合适的时间写回到主存中。
        由于写操作分配cache增加了cache内容预取的次数,增加了写操作的开销,但同时可能提高cache的命中率,
            因此这种技术对于系统的整体性能的影响与程序中读操作和写操作数量有关。

   缓冲技术的使用注意事项
        cache通常需要存储期间具有下面的特征:
        读取操作返回最后一次写入的内容,而且没有其他的副作用。
        写操作除了影响目标单元的内容外,没有其他副作用。
        对同一目标单元的两次连续读取操作将得到相同的结果。
        对同一目标单元的两次连续写操作将会把第二次写操作的值写入目标单元中,第一次写操作将没有意义。
        在ARM中,I/O操作通常被映射成存储器操作。I/O的输入/输出操作可以通过存储器的读取和写入操作实现。
        这样I/O空间就被映射成了存储空间。这些存储空间就不满足cache所要求的上述特性

        例如,从一个普通的存储单元连续读取两次,将会返回同样的结果。对于存储映射的I/O空间,连续两次读取,返回的结果可能不同,
            因为I/O引脚随时可能因外界环境而改变。因此对于存储器映射的I/O空间的操作就不能使用cache技术。

        由于写缓冲技术可能推迟写操作,它同样不适合对于存储器映射的I/O空间的操作
        由于上述原因,通常MMU都允许将某些地址空间设置成非缓冲的。MMU页表中地址转换条目的B位和C位就是用于控制乡音存储空间的缓冲特性。
        C位控制是否可以cache,置1可缓存。置0不可缓存。 B为用来控制是否可写缓冲置1允许,置0不允许
    存储系统的一致性问题
        当存储系统中引入了cache和写缓冲区时,同一地址单元的数据可能在系统中有多个副本,分别保存在cache,写缓冲区以及主存中。
        使得数据读操作可能得到的不是系统中"最新的"数值,这就带来了存储系统中数据的一致性问题。
        在ARM存储系统中,数据不一致的问题有一些是通过存储系统自动保证的,另外一些数据不一致问题则需要通过程序设计时遵守一定的规则来保证。
        地址映射关系变化造成的数据不一致:
            在虚拟地址到物理地址的映射关系发生变化前,如果虚拟地址A1所在数据块已经预取到cache中。
            当虚拟地址到物理地址的映射关系发生变化后,这时当CPU访问A1时,再使用cache中的数据块将得到错误的数据。

            同样当系统中使用了写缓冲区时,如果CPU写入写缓冲区的地址是虚拟地址,也会发生数据不一致的情况。
            在虚拟地址到物理地址的映射关系发生变化前,如果CPU向虚拟地址为A1的单元执行写操作,该写操作已经将A1以及对应的数据写入写缓冲区中。

            当虚拟地址到物理地址的映射关系发生变化后,则当写缓冲区将上面被延迟的写操作写到主存中时,使用的是变换后的物理地址,从而使写操作失败。
        为了避免发生上面所述的数据不一致的情况,在系统中虚拟地址到物理地址的映射关系发生变化前,根据系统的具体情况,执行下面的一些操作:
            :如果数据cache为写回类型,清空该数据cache(会写回主存)
            :使数据cache中相应的块无效
            :使指令cache中相应的块无效
            :将写缓冲区中被延迟的写操作全部执行
            :有些情况下可能还要求相关的存储区域被设置成非缓冲的。
        DMA造成的数据不一致问题
            DMA操作直接访问主存,而不会更新cache和写缓冲区中相应的内容,这样就可能造成数据的不一致。
            如果DMA从主存中读取的数据已经包含在cache中,而且cache中对应的数据已经被更新过,这样DMA读到的数据不是系统中最新的数据。
            同样,DMA写操作直接更新主存中的数据,如果该数据已经包含在cache中,则cache中的数据将会比主存中对应的数据“老”,也将造成数据的不一致。
            为了避免上述的数据不一致问题,执行下面的的一些操作序列:
                :将DMA访问的存储区域设置成非缓冲的
                :将DMA访问的存储区所涉及的数据cache中块设置成非缓冲的。
                :清空写缓冲区(执行写缓冲区中延迟的所有写操作)
                :在DMA操作期间限制处理器访问DMA所访问的存储区域
与cache和写缓冲区相关的编程接口
    寄存器C1中的相关位
        寄存器C1中与cache和写缓冲区操作相关的位有 C(bit[2]),W(bit[3]),I(bit[12]),RR[bit[14]]
    寄存器C7
        CP15的寄存器C7用于控制cache和写缓冲区。它是一个只写的寄存器。使用MRC指令读取该寄存器,将产生不可预知的结果。
    一些名词术语:
        清空:如果写回类型的数据cache中,如果包含有尚未写到主存中的数据,则将该数据写到主存中
        使无效:指将cache中的某个块或所有的块标识成无效,从而使所有访问这个块的操作都不命中。对于写回类型的数据cache来说,使无效并不把数据写回主存中
        清空写缓冲区:指终止当前代码的执行,将写缓冲区中所有被延迟的写操作执行完,也就是将写缓冲区中的数据全部写回主存中。
        cache内容预取:指在CPU访问某个虚拟单元,将包含该虚拟单元的存储块读取到cache中。
        等待中断激活:是ARM进入节能状态,停止执行,等待被异常中断激活。

    寄存器C7操作:MCR指令格式:
        MCR,p15,0,,c7,,  CRm和opcode_2的不同组合决定指令执行不同的操作
                CRm               opcode_2              含义                                       数据(Rd中的数据)
                C0                      4                   等待中断激活                                    0
                C6                      0                  使无效整个数据cache                          0
                C5                      0                  使无效整个指令cache                          0
                C10                     4                  清空写缓冲区                                      0
                C13                      1                  预取指令cache中的某块                 虚拟地址
························
    寄存器C9:
        寄存器C9是cache内容锁定寄存器。

快速上下文切换技术
    快速上下文切换技术(FCSE)通过修改系统中不同进程的虚拟地址,避免在进行进程切换时造成的虚拟地址到物理地址的重映射,从而提高系统的性能。
    通常情况下,如果两个进程占用的虚拟地址空间有重叠,系统在这两个进程之间进行切换时,必须进行虚拟地址到物理地址的重映射。而虚拟地址到物理地址的重
    映射涉及到重建MMU表,而且cache及TLB中的内同都必须使无效。这些操作将带来巨大的系统开销。
    快速上下文切换技术的引入避免了这种开销。它位于CPU和MMU之间,如果两个进程使用了同样的虚拟地址空间的,则对CPU而言,两个进程使用了同样的虚拟地址空间。
    快速上下文切换技术对各进程的虚拟地址进行变换,这样系统中除了CPU外的部分看到的是经过快速上下文切换机构变换的虚拟地址空间。
    这样在进行进程间切换时就不需要进行虚拟地址到物理地址的重映射。


    ARM系统中,4GB的虚拟地址空间被分成了128个进程空间块,每个进程空间块大小为32MB。每个进程空间块可以包含一个进程,
        该进程可以使用虚拟地址空间0x00000000-0x01FFFFFF.

    这个地址范围也就是CPU看到的进程的虚拟空间。系统128的进程空间块的编号0-127,
    编号为I的进程空间块中的进程实际使用的虚拟地址空间为(Ix0x02000000-Ix0x02000000+0x1ffffff),
    
这个地址空间是系统中除了CPU之外的其他部分看到的该进程所占用的虚拟地址空间。

    由VA(CPU发出的虚拟地址)到MVA(除cpu外部分看到的虚拟地址)的变换算法如下:
        if(VA[31:25]==0b0000000) then 
            MVA = VA |(PID<<25)
        else
            MVA = VA
    其中,PID为当前进程所在的进程空间块的编号,即当前进程的进程标识符。其取值为0-127。
    快速上下文切换机构使用进程的进程标识符代替VA的高7位,从而使得变换后的虚拟地址MVA。
    当VA的高7位不是全0,MVA=VA。这种VA是本进程用于访问别的进程中的数据和指令的虚拟地址,被访问的进程标识符不能为0.
    
    这里对快速上下文技术我之前也有过一些疑问:每个进程在内存中不是都有自己的虚拟地址映射表吗 。那么就算是相同的虚拟地址映射的也是不同的物理地址啊,
    那干嘛要用FCSE技术?

    这里给出自己的理解。 内存中的每个进程的确是都有自己在内存中的虚拟地址映射表。所以逻辑上都享有4G的内存。
    但是处理器只有一个MMU所以相当于内存中所有的
进程的映射表都是放在一个MMU管理的表中的。
    但是MMU管理的表中是不能有两个相同的虚拟地址映射到不同的物理地址的。所以CPU发出每个虚拟地址后要经过处理后才
会送给MMU。
    这样即使当每个进程都发送一个虚拟
地址A1,MMU收到的虚拟地址也是不相同的。这也就是上面提到的FCSE技术



快速上下文切换技术编程接口
    CP15中的寄存器C13用于快速上下文切换。指令格式:
        MCR p15,0,,,c0,0
        MRC p15,0,,,c0,0
    其中,在读操作时,结果中的位[31:25]返回PID,其他位的数值是不可以预知的。写操作将设置PID的值。
    PID的值为0时,MVA=VA,相当于禁止了FCSE。系统复位后PID即为0.
    当PID的值不为0时,相当于使能了FCSE。
指令预取和自修改代码
    在ARM中允许指令预取。在CPU执行当前指令的同时,可以从存储器中预取其后的若干条指令。
    程序执行过程中PC寄存器中的值为当前执行指令后第二条指令的地址。
    预取的指令并不一定能够得到执行。比如当前指令完成后,如果发生了异常中断,程序将会跳转到异常中断处理程序处执行,
    当前预取的指令将被抛弃。或者执行了跳转指令,则当前预取指令的指令也将被抛弃。

    自修改代码指的是代码在执行过程中可能修改自身。对于支持指令预取的ARM系统,自修改代码可能带来潜在的问题。当指令被预取后,
    在该指令被执行前,如果有访问指令修改了位于主存中的该指令,这是被预取的指令和主存中对应的指令不同,

    从而使执行的结果发生错误。
        比如下面就是一段自修改代码
            ldr r0,AddInstr ;将AddInstr标号的数据(即add,r1,r1,#1指令所表示的4字节数据)保存到r0中
            str r0,NextInstr ; 将 R0中的数据(即add,r1,r1,#1指令)写到NextInstr标号处,即覆盖了指令sub r1,r1,#1所表示的4字节数据
            NextInstr:
            sub r1,r1,#1
                .
                .
                .
            AddInstr:
            add r1,r1,#1
    这段指令中STR 指令修改了它后面紧接的指令,即将sub r1,r1,#1改成了add r1,r1,#1
    这段代码第一次执行时,STR指令后执行的是sub r1,r1,#1,因为主存中指令被修改前,sub r1,r1,#1 指令已经被预取。
    当这段代码第二次执行时,str执行后执行的就会是add r1,r1,#1,因为主存中的代码已经被修改了。
    同样下面的情况也会导致类似的情况
        如果在 str 指令执行后,跳转到异常中断处理程序执行。这时预取的指令sub r1,r1,#1将会被丢弃。当程序从异常中断返回时。
        重新进行指令预取,这是得到的就是修改后的指令即add r1,r1,#1。这样指令sub...即使在代码第一次执行时也不一定能得到执行。
        相反的,对于某些系统跳转到中断处理程序时,预取的指令会被保存,这样程序返回时,预取的指令sub...还是会执行,而add得不到执行。
        上述的不可靠代码的执行不能被ARM自动纠正,需要引入一定的变成规则来保证这种代码在arm体系中的可靠执行。
        IMB(Instruction Memory Barrier) 技术可以实现这一目标。

IMB技术
    IMB是一段特定的代码序列,IMB在新的指令被保存到主存中后,在该指令被实际执行之前执行,提供可自修改代码在ARM体系中的可靠执行。
    在很多ARM系统中,IMB中需要的很多指令(如使无效cache等)只能运行在系统模式下。而很多用户模式下运行的代码都需要运行IMB(类似linux中的屏障函数?)
    所以通常将IMB实现成一个SWI功能调用。
        同样在其他的一些场合也要在适当的时候运行IMB,比如对于采用了虚拟地址到物理地址映射的系统,如果在指令预取之后和该指令得到实际执行之前
        虚拟地址到物理地址的映射关系发生了改变,这是也需要运行适当的IMB
        如果在指令预取之后和该指令得到执行之前,该指令所涉及的存储区域的访问权限发生了改变,这是也需要运行适当的IMB。
阅读(2770) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~