MIPS Cache Architecture User Manual

MIPS Cache arch 1
The MIPS Cache
Architecture
CurrentVersion: 0.4 Date: 2008-05-30 Author: comcat <jiankemeng@gmail.com>
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 2
版本历史
0.1 comcat 08-03-21 初始化
0.2 comcat 08-04-02 完成 ch1
0.4 comcat 08-05-30 完成草稿
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 3
1. Cache 基本思想 5
1.1 相联方式
1.2 指令数据分离
1.3 多级 Cache
2. Cache 结构 9
3. Cache 工作方式 11
3.1 概述
3.2 Write-through or Write-back
3.3 Read-allocate and Write-allocate
3.4 策略综合
3.5 MIPS 实现实例
4. MIPS Cache 控制接口 16
4.1 TagHi and TagLo
4.2 cache instruction
4.2.1 ops
4.2.1 addr
4.3 Linux/MIPS Cache 操作的初步封装
5. Cache Aliases Issue 28
5.1 简述
5.2 现象
5.3 判断
5.4 解决
5.4.1 焦点
5.4.2 Linux Cache Flush API
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 4
5.4.3 改进
5.5 案例分析 34
5.5.1 现象
5.5.2 分析
5.5.3 探索
5.5.4 解决
5.5.4.1 保守的
5.5.4.2 激进的
6. Cache initialized on MIPS 45
6.1 Yamon 对 I-Cache 初始化
6.2 Yamon 对 D-Cache 初始化
6.3 4KE Cache 初始化参考实现
7. Write Buffer 50
7.1 概述
7.2 结构和工作方式
7.3 控制接口
Appendix: Debug Tips 53
A.1 SysRq Tips
A.2 Dump TLB
A.3 Testing KSEG2
A.4 验证 Cache Aliases
A.5 Dump Cache Tag
A.6 Testing DCache Tag Multiple Hit
Reference 67
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 5
1. Cache 基本思想
CPU 访问寄存器中的数据要比访问内存中的数据快几个数量级,这个在大量数据运算时,
CPU 的处理速度会受限于访存速度,为了平滑他们之间的速度差异,设计者根据程序局部
性原理引入了CacheCPU 访问它的速度介于寄存器与内存之间,起到了一个平滑作用。
实现 Cache 的花费介于寄存器与内存之间,这又是一个解决性能与价格矛盾的折衷。
Cache 的理论基础是程序局部性原理,包括时间局部性和空间局部性。即最近被CPU
访问的数据,短期 内 CPU 还要访问(时间 );被 CPU 访问的数据附近的数据,CPU 短期
内还要访问(空间)。因此如果将刚刚 访问过的数据缓存在 Cache 中,那下次访问时,可
以直接从Cache中取,其速度可以得到数量级的提高。
Cache 与内存之间交换数据以数据行”(Line)为单位,大小一般为 16 字节,32 字节或者
64 字节:
Figure 1: Cache and Memory
CPU 与数据 Cache 之间的数据交换则以字为单位(为获得较大的指令吞吐率,与指令
Cache 之间的数据交换则以数个字为单位,较常见的是128bit
CPU 要访问的数据在Cache 中有缓存则是为 命中 (Hit) ,反之则为 缺失 (Miss)
Cache 以行大小(Line size)为单位分成若干个行,内存逻辑上亦可如此,其皆可按地址由
低向高,依次 编号。因此 Cache 与内存就会有个映射问题,如:第四个内存行中的数据被
CPU访问时 ,该行将缓存于 Cache 中的哪一行?
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 6
1.1 相联方式
Cache 相联方式的不同,Cache 3 类:直接相联,全相联,组相联。
直接相联 Cache 的映射规则为:
Cache 行号 = 内存行号 % Cache总行数
假设某CPUCache共有2行,则Cache 与内存的映射关系为:
Figure 2: 直接相联 Cache Memory 之间的映射
直接相联 Cache 中,内存行都是映射 Cache 的固定行(直接用地址高位索引,无需
匹配)。这个在实际应用中,它的行冲突率会比较高,命中率会比较低。比如某段时间内
CPU 要不断的交叉访问2个映射到相 同 Cache 行的数据行,那么 尽管 Cache 有空间,
可是 CPU 不得不不来回填充Cache。它的点在于结构简单成本低。
相较于直接相联, 全相联 Cache 是一个极端,其允许任意内存行映射 到 Cache 的任意
行(不需索引,直接匹配)。缓存数据时,有空空,当所有行被用时,入的行则需要
一行,这个需要一个换算,常用的有 LRU(Least Recently
Used)RandomFIFO(First In First Out) 和 LFU(Least Frequently Used)。
全相联 Cache 有行合成一个组 (set), 当 CPU 查 找 Cache 时,CPU用地址同时与
Cache 有行的 Tag 相 比较(匹配)。因为任意的内存行可以缓存于 Cache 的任意行,
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 7
因此其能用 Cache 的存空间,行冲突率会比较低,命中率较高,实现起来硬件
电路复杂,价格昂贵,一般用在对性能要求苛刻 合,如 TLB
组相联 Cache 则是直接相联与全相联的一个折衷,兼顾性能与价格。 K 组相联,首先
Cache 分组,K 个行,映射时先索引组,其规则为:
Cache 组号 = 内存行号 % Cache总 组数
尔后,内存行可以映射到该组内的任意行上。缓存数据时,有空空,如组内有行被用,
使换算(LRU, Random, FIFO, LFU)一行。
Figure 2: 4 路组相联 Cache Memory 之间的映射
对于4组相联Cache,其组就有4 行。可以编号为 W0 ~ W3有组(Set)W0
合可以为第 0 ,其大小为 Cache_size/ways 。其他 3 以此类
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 8
1.2 指令数据分离
处理器的 L1 Cache 设计时基本哈佛结构,即将指令和数据分离,常为 I-
CacheD-Cache,其各自独立读写端口(I-Cache 只读,不需写端口)。其对性能
的提很明显的,指令取和操作数据的读写可以在同一时钟周期内进行,且已缓存的指
令,不会因 Cache 刷新或行换被增加流水线取指段的延迟
其缺点在于,位于内存的指令更新时,I-Cache 中的数据不会被更新当然在实际应
用中,动态改指令段的情况极少出现,如果有,则改指令软件负责 flush I-
Cache
1.3 多级 Cache
高性能的处理器往往带有 L2 Cache ,有的甚至带有 L3 Cache,其读写延迟依次增加,实
现的成本依次低。现统采用从 Register ---> L1 Cache ---> L2 Cache ---> L3
Cache ---> Memory ---> Mass storage 次结构,是为解决性能与价格矛盾所采
的实际可行的折中设计。
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 9
2. Cache 结构
K 路 组相联的 Cache 是目前使用最为广泛的 Cache 类型。如某 CPU 使用32KB大小、4
组相联行大小为16 Bytes L1 Cache ,则该 Cache 每组有4行,共有512组。其结
构如下图所示
组大小为 16B * 4 = 64B 每路大小为 32KB/4 = 8KB
该 Cache 的每行结构为:
其由 Tag 域、Status 和数据组成,
Tag 该行数据对应地址的高位。CPU 在索引到该组 (set) ,用相应地址与组内
行的 Tag 相比较,以之具体的行。
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 10
数据容纳的字节数是为行大小 (Line Size) ,其为 Cache 与内存之间数据交换的单位。
Status 则为一控制位信息(如Valid, Lock Parity check 等等),不同的
Cache ,不同的 Cache 实现 Status 域稍有不同,具体的可以参考相应 CPU 手册
对于 K 组相联的 Cache 因为组内有行被用时,需要指定将要被换的行,因此
组亦有一个用于路选 (Way-Select) 的数据。不同的换算对该数据的定使用亦
不同,例如 PowerPC E500 的 Cache 实现使用PLRU (Pseudo LRU) 算,8
Cache 路选域需要7位;对于MIPS 4KE 的 Cache 实现,其使用LRU算,4
Cache 路选域需要6位。关于这节可以参考相关的资料
些 MIPS Cache 的实现(如MIPS 4KE, 24KE, 34K etc. )提供 Software Cache
Testing 式可以程序员读出这个路选域,进判断出当前 Cache 工作常。
这个性在调试Cache相关问题时常有用。
路选数据合是为 Way-Select Array.
对于 I-Cache,因为其只读性,一性的维护容易的多,因此管理需要的控制要较
D-Cache 。如 4KE 的 D-Cache 实现,路选数据域外,还有 K 位的 Dirty
而 I-Cache 则不需要。具体的可以参考相应的CPU文档
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 11
3. Cache 工作方式
3.1 概述
K 路组相联 Cache 常工作方式是:组索引,然后理地址 (PA) 虚拟地址 (VA)
同时与组内K 行之 Tag 域同时匹配,有匹配则为命中 (Hit),尔后将命中的行中相应的字传
CPU
以上述 Cache 为例,常工作时其对地址的分如下所示
Addr[12:4] 索引组,9 bit 可索引 512 组
Addr[3:0] 行内索引字节,2^4 = 16 Bytes
代体系结构的 CPU 多数皆有 MMU,因其皆有虚拟地址空间与理地址空间。指令
中的访存地址皆为 VA,在访存操作送给RAM 控制器前 VA 换为 PA。Cache 的实现策
略则要灵活的多,具体的实现可以用 VA 索引,PA 匹配;亦可 PA 索引,PA 匹配;乃至
VA 索引,VA 匹配 (SB1 I-Cache, 20KC I-Cache) 甚至 PA 索引,VA 匹配 (R6000)。
最为常见的MIPS L1 Cache 实现是 VA 索引,PA 匹配;这实现可以在 VATLB换为
PA 时,Cache控制器同时用VA 索引 Cache 组,无需首先等待 VA 到 PA 的换,尔后再
索引匹配,因此其性能于 PA 索引,PA 匹配,但软件维护 Cache 性较复杂
且容易引起一看让人匪夷所思的问题。
VA 索引,PA 匹配 Cache 之工作方式
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 12
对于 L2 Cache ,因为性能的要求已那么苛刻,为复杂常的实现皆是 PA 索引,
PA 匹配。
是因为MIPS L1 Cache 实现时,执着于对性能的追求使得系程序员负担加重 :) VA
索引,PA 匹配的方式容易出Cache 别名 (Aliases)问题,这个需要对内核中凡是有
可能现 Cache 别名的地方都要谨慎周密以考。PowerPC 的系程序比较幸福
L1 Cache 的实现皆是PA索引,PA 匹配,因此他们根本不需要考虑 Cache 别名问题。
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 13
3.2 Write-through or Write-back
命中(store hit)时,Cache的实现亦有两种策略:Write-back 和 Write-through.
Write-through Cache ,在 write hit 时,会将数据更新到 Cache 和 RAM.
Write-back Cache ,在 write hit 时,则将数据更新到 Cache 将被更新的行
'dirty'该行被换时控制器将该行数据写回到内存。
对于 Write-back 的 Cache ,在连续多次数据时可以节线带宽,性能要于 Write-
through由于其缓存的数据往往是最的,与内存中的数据多数时是不一的,因此
需要软件来维护其一性。
3.3 Read-allocate and Write-allocate
数据时 Cache miss ,实际实现中有 2 策略:Write-allocate 和 No write-
allocate. 者的处理方式是分配一行,从 RAM 数据填充之(相于一个 read
miss refill 过程),最后才将数据入 Cache(到此,亦会根据). No read-allocate
(Write-around) 的处理方式则是过这一级 Cache (不分配 Cache line),直接将数据
到下一级 Cache/Memory. 些 MIPS 的实现两种写策略皆支持
数据时 Cache miss ,实际实现中亦有 2 策略:Read-allocate 和 No read-allocate
(Read through). 的实现一般皆为 Read-allocate ,即:从 Cache 中分配一行,
从 RAM 数据填充之,尔后将数据传给 CPU. No read-allocate 则是直接从 RAM
取数据到CPU(不经Cache )。若非特别策略皆默认Read-allocate.
3.4 策略综合
策略的用比较简单,一般皆为 Read-allocate,一般不会特别,有些文档直接提
Write-through/Write-back with Read-allocate 是指此实现非 Write-allocate,即其
策略为 No write allocate.
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 14
策略的一个总结:
Write Through Write Back
Write
allocate
On hits it writes to cache and main memory;
On misses it updates the block in main memory and brings the block to the cache;
Bringing the block to cache on a miss does not make a lot of sense in this combination because the next hit to this block will generate a write to main memory anyway
On hits it writes to cache setting “dirty” bit for the block, main memory is not updated;
On misses it updates the block in main memory and brings the block to the cache;
Subsequent writes to the same block, if the block originally caused a miss, will hit in the cache next time, setting dirty bit for the block. That will eliminate extra memory accesses and result in very efficient execution compared with Write Through with Write Allocate combination.
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 15
Write Through Write Back
No write
allocate
On hits it writes to cache and main memory;
On misses it updates the block in main memory not bringing that block to the cache;
Subsequent writes to the block will update main memory because Write Through policy is employed. So, some time is saved not bringing the block in the cache on a miss because it appears useless anyway.
On hits it writes to cache setting “dirty” bit for the block, main memory is not updated;
On misses it updates the block in main memory not bringing that block to the cache;
Subsequent writes to the same block, if the block originally caused a miss, will generate misses all the way and result in very inefficient execution.
3.5 MIPS 实现实例
Au1100/Au1200 L1 D-Cache: Write-back with read-allocate (no write-allocate)
20Kc L1 D-Cache: Write-through with no write-allocate
Loongson2E/2F L1 D-Cache: Write back with no write-allocate
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 16
4. MIPS Cache 控制接口
MIPS 系结构引入了如下的寄存器和指令作为软硬件的接口,便软件管理 Cache:
4.1 TagHi and TagLo
TagHi 和 TagLo 用于存 Cache 行的 Tag 数据,皆为 32 位 CP0 寄存器;其中
TagHi 理地址过 36 位时使用。行 Index load tag 操作,则读出 Cache
行的 Tag 于这对寄存器中;行 Index store tag 操作,则将寄存器中的数据入对应的
Cache 行的 Tag 。实际应用中,这个寄存器要在 Cache 初始化时用到,用在将
知状态的 Cache 行的 Tag 域置为 0。
MIPS 系结构设计哲学就是能让软件做,尽可能让软件做。因此 Cache 的初始化
(上电后 Cache 状态未知,一般都是由硬件来初始化),也留给软件。参考的 Cache
初始化过程可能参看后面的第 6
4.2 cache instruction
不同于 PowerPC 引入多条 dcbX, icbX 指令管理 Cache,MIPS 系结构引入
cache 指令作为软件控制 cache 一接口,于对哪个 Cache (L1 I, L1 D, L2, L3)
何种操作皆由一个整型值 ops 指定:
cache ops, addr
4.2.1 ops
ops 进 4 字节的指令,用 5 位,低 2 位指定 Cache 型 (L1 I, L1 D, L2, L3),高
3 位指定行的操作。
其能指定的基本操作有:
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 17
Index Invalidate(Writeback) 000
Index Load Tag 001 读 Cache 行之Tag
Index Store Tag 010 写 Cache 行之Tag
Hit Invalidate 100
Fill, Hit Writeback Invalidate 101
Hit Writeback 110
Fetch and Lock 111
MIPS32/64 系结构规定必须实现3个:Index Invalidate(Writeback), Index Store
Tag, Hit Writeback Invalidate,实际中最常用的就是这3个操作。
便记忆可用如下的义代替数字:
Index_Invalidate_I 0x00 (000 00)
Index_Writeback_Inv_D 0x01 (000 01)
Index_Writeback_Inv_SD 0x03 (000 11)
Index_Load_Tag_I 0x04 (001 00)
Index_Load_Tag_D 0x05 (001 01)
Index_Store_Tag_I 0x08 (010 00)
Index_Store_Tag_D 0x09 (010 01)
Hit_Invalidate_I 0x10 (100 00)
Hit_Invalidate_D 0x11 (100 01)
Hit_Invalidate_SD 0x13 (100 11)
Hit_Writeback_Inv_D 0x15 (101 00)
Hit_Writeback_Inv_SD 0x17 (101 11)
ARM 用 Coprocessor 寄存器指令 MCR 实现 Cache 的管理:
MCR p15, 0, <Rd>, c7, <cN>, <opcode2>
<cN> 和 <opcode2> 组合,指定要的操作,类于 ops。
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 18
相较于 ARM,MIPS 的设计要简单、优美的多。
4.2.1 addr
addr 是为一个地址 (PA / VA) ,用于选择针对 Cache 哪一行进行操作。有两种操作类
Hit 和 Index。Hit 的操作类似 Cache 常工作方式,其过程为: 用 addr 的组
位(位12~4 )索引组,同时将 VA TLB 转换为 PA 然后匹配 Tag ,命中 (Hit) 则对相
应的行行操作,
为了能刷新 Cache 时能精确访问到具体的行,MIPS 系结构在 Hit 的访问方式上又引
入了 Index 的方式:该方式无需匹配(不需要实地址换),组选后直接用地址的中
部(位14~13)进行组内索引(路选):
Figure 8: Indexed 方式地址分解
Index 的操作 ,能使虚拟地址 (VA) 精确操作组内的某一行,可用于不知道物理地址
(PA) 合。如在一个进程的内上下中,快速flush 个 L1 D-Cache,按行
Index_Writeback_Inv_D dcache_size 大小的址空间即可。
cache 指令可以引起 TLB Refill 异常(ExeCode: TLBL),TLB Invalid 异常,不会引起
TLB Modified 异常。
对于 Index 的操作,addr 使用不经 TLB 映射的(unmapped) 的地址,避免引起 TLB
异常。此对 PA 索引的 Cache 而言,VA 索引的 Cache,Index 的操作根本不会
TLB
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 19
---------------------------------------------------------------------------------------------------------------
From BCM7410:
An indexed Cache inst. such as indexed invalidation, load tag and store tag must use an operand address in a unmapped segment, otherwise it may cause a unexpected TLB exception or it may apply to an erroneous Cache location.
From MIPS32 R1/R2:
For index operations (where the address is used to index the Cache but need not match the Cache tag) software should use unmapped addresses to avoid TLB exceptions. This instruction never causes TLB Modified exceptions nor TLB Refill exceptions with a cause code of TLBS.
From TX49:
TLB Refill and TLB Invalid exceptions can occur on any operation. For Index operations (where the physical address is used to index the cache but need not match the cache tag) unmapped addresses may be used to avoid TLB exceptions. This operation never causes TLB Modified or Virtual Coherency exceptions.
:以上是对 PA索引,PA匹配的情况
---------------------------------------------------------------------------------------------------------------
特别留意 有一部分 MIPS Cache 的实现使用地址的最低位 (LSB, Least Significant Bit)
进行路选,如东芝 TX49 的实现,其4 组相联 Cache 索引方式访问使用 Addr[1:0]
作为路选
[10] Page A-39
其它多的 MIPS 实现并没有在其文档里非清晰注明这个,实际使用中要注意。 一个
简单的方就是查看Linux Kernel 里 struct cache_desc 结构中的 waybit 成,若其
为 0 ,则其使用 LSB 进行路选 (参下节)。如 NEC VR5500, R10000, Loongson2E
使用 LSB 作为其路选位。如果,可以测试函数,Index_Load_Tag_D
0x8000 0000 ~ 0x8000 0002 的 Tag 其是相同,更严谨的可以将 0x8000
0001 处的 Tag 为0 尔后再 Index_Load_Tag_D 0x8000 0000 ~ 0x8000 0001
2 个 Tag。
4.3 Linux/MIPS Cache 操作的初步封装
有 Cache 操作的初步封装皆位于:[include/asm-mips/r4kcache.h]
其定, __BUILD_BLAST_CACHE 和 __BUILD_BLAST_CACHE_RANGE
用于如下数:
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 20
blast_xcachexx(void) # 以 Indexed 方式 flush 个 Cache
blast_xcachexx_page(addr) # Hit 方式 flush addr 处的一个 Page
blast_xcachexx_page_indexed(addr) # 以 Indexed 方式 flush addr 处的一个Page
blast_xcache_range(start, end) # Hit 方式 flush start 到 end 在 Cache 中的内
protected_xcache_range(start, end) # Hit 方式 flush start 到 end 在 Cache 中的内
是一些预处理的实例:
blast_icache16()
blast_dcache16()
blast_icache32_page()
blast_dcache32_page()
blast_icache128_page_indexed()
blast_dcache128_page_indexed()
blast_dcache_range()
blast_inv_dcache_range()
16, 32, 128 为行大小
些函数会被位于 arch/mips/mm/c-r4k.c 中的
flush_cache_all/flush_cache_page/flush_cache_range/... 所调用。
先看看所有 __BUILD_BLAST_CACHE 的用:
396 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
397 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
398 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
399 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
400 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
401 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
402 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
403 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
404 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
用到的 Cache 操作有:Index_Invalidate_I/Hit_Invalidate_I,
Index_Writeback_Inv_D/Hit_Writeback_Inv_D,
Index_Writeback_Inv_SD/Hit_Writeback_Inv_SD。单从能上OS 仅仅使用了索
引方式的写回置ICache ,无需写回)和命中方式的写回置ICache
Author: comcat <jiankemeng@gmail.com>
MIPS Cache arch 21
)。行大小为 16 和 32字节的有一套函数;实际中尚未到64字节行大小的
L1 DCache ,因此仅 L1 ICache 和 L2 需要一组数;行大小 128 字节的 Cache
L2 Cache 义 128 字节行大小的 SCache 即可。
宏 __BUILD_BLAST_CACHE 的定如下:
342 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
343 #define __BUILD_BLAST_CACHE (pfx, desc, indexop, hitop, lsize) \
344 static inline void blast_##pfx##cache##lsize(void) \
345 { \
346 unsigned long start = INDEX_BASE; \
347 unsigned long end = start + current_cpu_data.desc.waysize; \
348 unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \
349 unsigned long ws_end = current_cpu_data.desc.ways << \
350 current_cpu_data.desc.waybit; \
351 unsigned long ws, addr; \
352 \
353 __##pfx##flush_prologue \
354 \
355 for (ws = 0; ws < ws_end; ws += ws_inc) \
356 for (addr = start; addr < end; addr += lsize * 32) \
357 cache##lsize##_unroll32(addr|ws,indexop); \
358 \
359 __##pfx##flush_epilogue \
360 } \
361 \
362 static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
363 { \
364 unsigned long start = page; \
365 unsigned long end = page + PAGE_SIZE; \
366 \
367 __##pfx##flush_prologue \
368 \
369 do { \
370 cache##lsize##_unroll32(start,hitop); \
371 start += lsize * 32; \
372 } while (start < end); \
373 \
374 __##pfx##flush_epilogue \
375 } \
376 \
377 static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
378 { \
379 unsigned long indexmask = current_cpu_data.desc.waysize - 1; \
380 unsigned long start = INDEX_BASE + (page & indexmask); \
Author: comcat <jiankemeng@gmail.com>
Loading...
+ 46 hidden pages