之前遇到了linux random kernel panic的问题,原因是TLB的entry对应的page其实已经释放。

 

VIP是独立的ko,create resource是通过VA接口走到我们ko的allocation接口,

unmap gart后,没有invaliate tlb,再create allocation,使用了 同样的va,从tlb 拿PA,结果write到了已经释放的page上。

invaliate gart cache走的是mmio而不是dma,不用等待dma fence back。

现在inv tlb是在submit task里面做的,改成在map gart或者destory allocation时也做。

这里直接invalidate了tlb,降低了性能。

 

TLB资料:

http://www.wowotech.net/memory_management/tlb-flush.html

TLB flush操作

Linux VM subsystem很多场合要对TLB flush,下面描述了TLB概念,硬件实现,TLB flush的软件接口,内核版本是4.4

1,概念

what's TLB:Translation Lookaside Buffer,

处理器在取址或者执行访问memory指令时需要进行地质翻译,即把虚拟地址翻译成物理地址。

但地址翻译是个漫长的过程,要遍历几个level的translation table,是严重开销。

为提高性能,在MMU增加TLB单元,把地址翻译关系保存在这个高速缓存中,以省略对内存中页表的访问。

why need TLB?

TLB本质是一种cache,cache的存在就是为了更高的performance,

instruction cache,指令缓存,

data cache

translation cache

 

instruction cache解决cpu获取main memory中的指令数据(地址保存在PC寄存器)的速度慢的问题而设立的。

data cache是为了解决数据访问指令比较慢而设立的。

而这这是事情的一部分,看看程序中数据访问指令的执行过程:

1,将PC的虚拟地址反应成物理地址

2,从memory获取数据访问指令(假设该指令需要访问地址x)

3,将虚拟地址x翻译成物理地址y

4,从location y 的memory获取数据

 

instruction cache解决了2的性能问题,data cache解决了step 4的性能问题。

复杂的系统会建立各个level的cache来缓存main memory的数据,而他们只加速了2,4步骤,

IC设计师不会放弃1,3的,这也是TLB的由来。

若CPU core发起的地址翻译过程可以在TLB(translation cache)中命中(cahche hit),CPU不需要访问慢速的main memory提高了performance

 

how TLB work?

图片来自计算机的组成与设计,computer organization and design

how TLB work

 

当要转换VA到PA时,首先在TLB找是否有匹配的条目,若有,称为TLB hit,则不用再访问页表完成地址翻译。

TLB始终是全部页表的一个子集,所以可能在TLB找不到。

若没有在TLB中找到对应的item,称为TLB miss,就需要访问memory的page table完成地址翻译,同时将翻译结果放入TLB,如果TLB满了,还要设计替换算法决定哪个TLB entry要失效,以加载新的页表项。

TLB entry的内容包括:

1,物理地址,physical page number,这是地址翻译的结果。

2,虚拟地址,virtual page number,用cache的术语描述叫Tag,进程匹配时就是对比Tag。

3,memory attribute,如memory type,cache poliocies, access permissions

4,status bits,如Valid, dirty,reference bits

 

三,ARM v8的TLB

选择cortex-A72 processor来描述ARMv8的TLB的组成结构和维护TLB的指令。

1,TLB的组成结构,下图是A72的功能block:

how TLB work

A72实现了2个level的TLB, 绿色是L1 TLB,包括L1 instruction TLB(48-entry fully-associative) 和 L1 data TLB(32 entry fully-associative)。黄色block是L2 unified TLB,它要大一些,可荣亚1024个entry,是4-way set-associative的。

当L1 TLB发生TLB miss时,L2 TLB是它坚强的后盾。

 

2,如何确定TLB match?

地址翻译过程不是VA->PA的映射那么简单,系统中的虚拟地址空间很多,每个地址空间的翻译都是独立的。

1)每个进程有自己独立的VA空间,各进程里,相同的VA翻译成不同的PA。

2)若支持虚拟化,系统中存在一个hostOS和多个guest OS,不同OS间地址翻译不同,

3)

我们可以不考虑复杂的情况,在进程切换、虚拟机切换、secure/normal world切换时,将TLB所有内容全flush(invalidate),这样设计很轻松,但性能下降。

实际设计TLB时,会让TLB entry包含和虚拟地址空间context相关的信息,A72里,满足下面条件,才算匹配了一个TLB entry:

1)请求进程地址翻译的VA page number等于TLB entry中的VA page number

2)请求进程地址翻译的memory space identifier等于TLB entry的memory sppace identifier。

所谓memory space identifier就是区分请求是来自EL3 Exception level,nonsecure EL2 exception level,Sucure and nonsucrue EL0.。。。。

3)若entry标记为non-Global.,请求进行地址翻译的ASID等于TLB entry的ASID

4) ....

3,进程切换和ASID(address space identifier)

进程有自己独立的VA,若TLB不标识VA,进程切换是,VA变化,TLB的entry也应该无效了要invalidate all,

但这么做从功能上没问题,性能却下降。

好的方案是区分global pages(内核地址空间)和process-specific pages,

Global pages,所有进程一样,进程切换后仍然需要这些entry,不用flush TLB,

Process-specific pages的TLB entry,一旦切换,TLB不能识别,就要flush掉上一个进程VA的TLB entry。

若支持ASID就不通了,TLB 的entry,保存多个相同的VA到不同的PA的映射也是可以的,只要他们有不同的ASID。

 

4,TLB的一致性问题,

TLB也是一种cache,有cache就意味着数据有多个copy,所以存在一致性coherence问题。

与数据,指令cahce或者unified cahche不同的是,硬件不维护TLB的coherence,一旦软件修改了page table,软件也要进程TLB invalidate操作,以维护TLB coherence。

 

5,TLB操作过程

四,TLB flush API

 

invalidate使无效

https://blog.csdn.net/qingfengjuechen/article/details/83749946

clean:对于回写类型的数据cache,若包含尚未写到主存的数据,则将数据写到主存

invalidate:将cache的某个块(或者所有)标识成无效,使所有访问这个块的操作一定是不命中。对于写回类型的数据cache来说,使无效,并不使数据写到主存中。(invalidate=flush)

 

相关文章: