Chinaunix首页 | 论坛 | 博客
  • 博客访问: 936067
  • 博文数量: 633
  • 博客积分: 30780
  • 博客等级: 大将
  • 技术积分: 7532
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-12 21:07
文章分类

全部博文(633)

文章存档

2011年(10)

2010年(500)

2009年(47)

2008年(76)

我的朋友

分类: 嵌入式

2011-04-30 11:21:12

------------------------------------------
转载请注明出处:http://lullaby2005.cublog.cn/
------------------------------------------

 这是我学习IA的cache时的笔记,绝大部分是阅读intel manual system programming卷一的总结,或者说是自己理解以后的翻译。

先上一张图:

这是pentium4xeon CPUcache相关的硬件模块。你看,有L1L2L3cache, TLB,store Buffer

(疑问:为什么没有L1instruction cache?(见table11-1关于L1 instruction cache的说明)是不是L2L3cache就不分data部分和instruction部分了?)

 

几个术语的解释:

Cache line fill processor读一块memory并且发现这块memorycachable的(通过MTRR来决定改块memory是否cachable),那么processor会把整个cache line读取到L1L2L3cache

 

Cache hit:当处理器要读取一块memory的内容时,发现这块内容已经存在cache中了,那么这就称为cache hit

 

Write hit 当处理器要写内容到一块memory时,发现cache中已经有这块memory对应的cache了,那么就叫write hit。它会先写到cache,再根据当前系统的写策略决定是否要同时写到memory

 

 

Cache类型:

IA中,Cache类型一共有6种,

 

l  Strong Uncacheable UC

这种cache类型的memory,任何读写操作都不经过cache。一般是memory-mapIO地址可以使用这种类型。一般的ram强烈推荐不使用这种cache,否则效率会非常低。

 

l  Uncacheable UC-

特性与UC(Strong uncacheable)相同,唯一不同的是,这种类型的memory,可以通过修改MTRR来把它改变成WC

 

l  Write Combining WC

这种类型的cache,特性与UC相似,不同的地方是它可以被speculative read(什么叫speculative read?)每次write都可能被delaywrite的内容会buffer到一个叫“write combining buffer”的地方。可以通过 MTRR编程来设置WC,也可以通过设置PAT来设置WC(pat是什么?)

 

l  Write – through WT

这个很好理解,每次write,都要writememory,同时write到对应的cacheif write hits)。WT方式保证了cachememory是一致的。

 

l  Write – back (WB)

这种类型的memoryreadwrite,都跟一般的cache一样。只是write的时候,当写到了cache中,不会立即writememory里(这个就跟WT不一样了)。CPU会等到适当的时候再writememory比如当cache满了。 这种类型是效率最高的类型,

 

l  Write-protected WP

Readwb一样,但每次write,都会引起cache invalidate

 

 

cache控制方法

IA里,对cache的控制方法有2个方面:cache控制寄存器和cache控制指令,我们分别来看一下:

1.       Cache控制寄存器

先上一个全局图

CR0CD bit:一个系统全局的cache enable bit CDclear,系统整个的cache机制打开,但还是要受到单个page或者某个region自己的策略的限制;当CDset,整个系统的cache机制就关闭了。

 

 

cache的全局bit CR0 (CD&NW) clear时(也就是cache功能被全局打开)的基础上,MTRRphysical memory area-level)与PATpage-level)如果定义不一样,那么以如下的表格为准:

 

cache已经生效了,CPU怎么禁止cache呢?这里有一个固定的套路:

1)  设置全局bit,使全局的cache进入到no-fill mode(设置CR0CD1,并且设置NW0);(这一步是为了不再使memory access产生miss并再一次填充cache

2)  Flush所有的cache(通过指令WBINVD)(这一次是为了让cache里的东西flushmemory

3)  DISABLE掉所有的MTRR并且设置默认的cachetypeuncache(这一步就是最后的关cache了)

注意到intel手册里有这么一段话:

For the Pentium 4 and Intel Xeon processors, after the sequence of

steps given above has been executed, the cache lines containing the

code between the end of the WBINVD instruction and before the

MTRRS have actually been disabled may be retained in the cache

hierarchy. Here, to remove code from the cache completely, a second

WBINVD instruction must be executed after the MTRRs have been

disabled.

这里我有疑问?为什么上面三条步骤做了以后,第二条和第三条之间的代码还保留在cache里?第二条中的WBINVD不是应该flush掉所有的cache里的东西包括23之间的代码吗?

 

2.       Cache控制指令

1)       INVD 仅仅是invalide L1L2L3 cache,但不会把cache里的内容write back to memory;

2)       WBINVD : INVD相比,多了write back to memory action

3)       PREFETCHh:软件用这条指令来指示处理器把某块内容需要放入到哪块cache里,相当于是软件在干预cache的一些行为。注意,这个PREFETCHh只能预取data,不能预取instruction

4)       CLFLUSH PREFETCHh相反,CLFLUSH让软件有机会决定cache里的哪些cache line应该被flushmemory中去,同时这段cache也就被free了。

5)       Non-temporal move instructions (MOVNTI,MOVNTQ, MOVNTDQ, MOVNTPS, MOVNTPD) (这些都是SSE/SSE2扩展的指令): 用于把register里的内容直接写入memory,而不必经过L1L2L3 cache,避免了cache污染。

 

隐式cache

很多时候,系统中会隐式cache一些东西,软件(software)必须做一些事情来避免隐式cache带来的问题,比如这个INTEL汇编的例子:

 

我们假设线性地址F000H对应的物理地址是B000H,这个对应关系在页表中有记录,同时在TLB中也有记录。这个页表项所在的地址是PTE_F000。现在我们想修改这个对应关系,把物理地址B000H换成A000H。如果我们直接这样:

mov PTE_F000, A000H; Change F000H to point to A000H

mov EBX, [F000H];

第一条指令看似已经把页表项的内容修改成了A000H,然后第二条指定就把线性地址F000H的内容moveEBX中。在CPU运行第二条指令访问线性地址F000H时,会先走TLB。由于TLB中的任然存放着F000H-B000H的映射,所以第二条指定错误的把物理地址B000H的内容move到了EBX中了。显然这个问题的根本原因,是TLB隐式的cache了页对应关系。

通过加入两行代码可以刷新TLB

 

mov EAX, CR3; Invalidate the TLB

mov CR3, EAX; by copying CR3 to itself

mov PTE_F000, A000H; Change F000H to point to A000H

mov EBX, [F000H];

 

MTRR

MTRR: Memory Type Range Register,提供了这样一个机制:让不同范围的物理地址空间,具有不同的cache方法(UC,UC-,WC,WB,WT,WP之类的)。

MTRR允许定义最多96个物理内存范围,通过MSR来指定不同范围的MTRR具有哪些cache方法。

这里有一个全貌图:

 

从这里可以看到,0-1M是用于fix-range map的,1M以上的物理地址空间是用于variable-ranged map的。

 

另外还可以通过这个table看到不同的cache typeMTRR中是怎样被encode的:

 

1 MTRRfeature    identification

软件通过CPUID指令可以知道当前系统是否支持MTRR。如果系统支持MTRR,那么关于MTRR的更多的详细信息可以通过运行instruction RDMSR 来读取64bit的只读IA32_MTRRCAP MSR寄存器得到,下图是这个IA32_MTRRCAP MSR的组成:

看下每个域表示什么意思:

VCNT:当前系统中实现了多少个variable memory ranges (见上面的figure11-4

FIX: 如果被set,表示系统支持fixed range;如果被clear,表示系统不支持fixed range(见上面的figure11-4

WC: 如果被set,表示系统支持write combinecache方法,反之亦然;

SMRR:如果被set,表示系统支持system management range register(关于这个SMRR,我也不知道具体是怎么回事?)

 

2 如何用MRTT来设置系统中的physical cache method

这里涉及到三个register IA32_MTRR_DEF_TYPE MSR the fixed-range MTRR the variable-range MTRR.

IA32_MTRR_DEF_TYPE MSR: 用来设置MTRR中没有涵盖到的物理内容的cache属性,也就是默认的属性,照例还是先看寄存器的组成:

 

Type:很明显,存放的就是cache 属性的编码(也就是前面图中提到的UC,UC-,WC,WT,WP的值),有效值是0,1,4,5,6

FE: (Fixed-range MTRR enable/disable) 当该bitset,说明系统中fixed-range MTRRenable的;反之亦然。

E: 相当于一个全局的MTRR开关。这个bitset时,表示全局的MTRRenable的,如果同时FEclear,表示除了fixed-rangeMTRRdisable外,其他的MTRR都是enable。如果Eclear了,那么系统中的所有MTRR都被clear,即使这是fixed-rangeMTRRenable,也无济于事。

 

the fixed-range MTRR 系统中有11fixed-range的寄存器,每个寄存器64bit。这64bit又被分成8bit一组。也就是说每8bit可以描述一个fixed-rangememory。所有11个寄存器可以描述11*(64/8) = 88个,刚好与figure11-4fixed-range MTRR对应上了(64+16+8 . 疑问:每8bit描述一个fixed-range,这8bit的分布是怎样的?(即在哪里指定type?)

 

the variable-range MTRR:由寄存器pair IA32_MTRR_PHYSBASEIA32_MTRR_PHYSMASK来指定variable-range的描述,看下图:

 

 

注意,在variable-rangeMTRR中,是有对齐原则的:

最小的范围是4Kbase地址也至少是4KB对齐;

如果范围大于4K,那么范围必须是2N次方(N大于12),base地址对齐也必须是2N次方。

 

对于MTRR的使用,有如下的一些规则:

1.       如果MTRR没有被enableMSR IA32_MTRR_DEF_TYPE中的E flagclear),那么所有的内存访问都使用UC类型.

2.       如果MTRRenable了:

2.1) 访问的地址在0-1M之间的话,并且fix-ranges MTRRenable的,那么就使用fix-rangeMTRR指定的cache type

2.2 访问的地址在1M以上,那么就通过variable-ranges MTRR指定的type来决定:

2.2.1 如果只有一个variable-range MTRR包含了这个地址,那么就使用该MTRRtype

2.2.2 如果有一个以上variable-range MTRR包含了这个地址,并且这些MTRRtype都一样,那也使用这个type

2.2.3 如果有一个以上variable-range MTRR包含了这个地址,并且其中一个MRTTtypeUC,那就使用UC

2.2.4 如果有一个以上variable-range MTRR包含了这个地址,并且typeWTWB,那么就使用WT(WT优先)

          2.2.5)如果以上规则都没满足,那么这块地址的访问的cache typeundefine

3. 如果访问的地址没有fix或者variable rangeMTRR match到,那么就使用系统默认的cache type(疑问?系统默认的cache type是在哪里设置呢?)

 

MTRR初始化:在系统hardware reset时,CPU会自动清除variable-ranged MTRRflag,并且会清除掉MSR IA32_MTRR_DEF_TYPEE标志(表示disable所有的MTRR.在初始化MTRR之前,软件(bios或者OS)必须初始化所有的fix ranged variable ranged MTRR0。然后软件再根据系统需求的实际情况去设置各个MTRR

 

MP系统中,MTRR的处理需要the care should be taken:

各个processor必须保证所有的MTRR都一样,即各个processor所看到的memory cache type都必须具有一致性。这个一致性不是硬件提供的,而是software来确保的。。

 

PAT-- Page Attribute Table

MTRR是基于物理地址空间来决定某块物理地址具有什么样子的cache属性。而PAT是对MTRR的补充,PAT允许CPU基于线性地址来决定某个page(线性地址页)具有什么样子的cache属性。

 

PAT是在页表项或者页目录项里指定的(见前面的figure11-3),并且PAT要与页表项或者页目录项里的PCDPWT这两个bit一起来决定某个page具有什么样子的cache属性(UC,UC-,WB,WT,WC)。这些cache属性在PAT概念里的编码如下:

 

可以通过CPUIDEAX=1)来判断当前CPU是否支持PAT。软件可以通过编程MSR IA32_PAT(277H)来设置PAT的相关属性。注意,只要是支持PATCPUPAT就一定是打开的,也就是说,CPU没有control bit可以控制PAT的开和关。

 

这是MSR IA32_PAT(277H)bit分布

64bitMSR,分成了8PA域。

那么,系统怎样来指定某个页具有什么样子的cache 属性呢?

页表中的PAT,PCD,PWT3bit,这3bit组合起来,可以索引到MSR IA32_PAT(277H)的某个PA,这个PA的值,也就是那5cacheencoding值。页表的PAT,PCD,PWT组合情况如下:

很直白吧。

当系统上电时,那8PAT entry会有一个默认值,如下:

这些默认值,可以通过WRMSR指令写IA32_PAT来改变(这个MSRring0级别是可读可写的)

或许你有这样一个疑问:既然PAT是基于线性地址的,那么是否存在这样的情况:当一个物理页表被MMU映射到了不同的两个page,并且这两个page entrypat属性都是不一样的,那怎么办? 这个问题,从intel的角度来看,是undefine的。即INTEL不建议OS这样做,如果非要这样做,导致的后果unknow,也就是后果自负J

阅读(2108) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~