文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

loongarch架构介绍(四)TLB异常处理

2024-11-30 19:04

关注

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

前言

上一篇文章中介绍了loongarch架构中的地址翻译模式及其配置方法,涉及到虚拟内存系统中页表相关的管理。本文中则介绍TLB相关的异常处理,并结合代码进行分析。因为loongarch架构中采用的是一种软件管理TLB的方法,所以其处理流程和软件所需要进行的管理操作与很多常见的架构不同。

1、TLB表项和页表项

首先介绍TLB表项和页表项的格式,作基本的了解。

(1)页表项格式

下图为loongarch中的页表项格式:

下面为各位的说明:

其中,大页的页表项和基本页的页表项在格式上的主要区别是H位和G位。并且基本页的页表项在末级页表,而大页的页表项实际上是替代了原来的页目录项。

另外,对于基本页的页表项,loongarch中每个页表项存放了相邻的一对奇偶相邻页表信息。如下图:

(2)TLB表项格式

下图为loongarch中的TLB表项格式:

其中,每个TLB表项分为两个部分:第一行为比较部分,下面两行为物理转换部分。

TLB表项的比较部分包括:

因为TLB和页表双页存储的特性,每个TLB表项中有两个物理转换信息。物理转换信息中PPN即物理页号,其他和上文中页表中的对应。

2、软件管理TLB

类似于MIPS架构,loongarch中使用的是一种软件管理TLB的方式。在大多数其他的架构中,采用的都是通过硬件管理TLB的方式。软件管理TLB带来了更多的灵活性,但性能相对较差。

硬件管理TLB中,在忽略page fault的细节和cache的情况下,虚拟地址转换到物理地址的过程如下图:

其中,TLB miss后查找页表的这个过程是由硬件自动完成的,软件只需处理后面产生的page fault。整个过程中最多产生一次page fault。

下图则为软件管理TLB方案中虚拟地址转换到物理地址的过程:

具体解释如下:

  1. TLB miss后会产生第一次TLB重填(TLB refill)异常,在TLB重填异常中需要软件去遍历页表并填充TLB表项,这里应该是软件管理TLB和硬件管理TLB最大的不同。
  2. 然后TLB重填异常处理中,如果填充的页表项仍然无效,那么在返回后再次查询TLB时,会第二次产生其他的fault处理,以填充页表项、或填充页表项和TLB项。
  3. 如果第二次fault处理中没有重填TLB表项,那么在返回后再次查询TLB时,还会产生第三次TLB重填异常。

可以看到,TLB miss后查找页表的这个过程需要软件进行处理,并且整个过程中最多能产生三次异常。

另外,硬件上会保证在TLB重填异常中不能再次产生TLB重填异常。

3、TLB相关异常

loongarch中TLB相关的异常有:

其中,TLB重填异常时需遍历页表进行重填工作。TLB重填异常于一般的异常不同,其拥有独立的异常入口、独立的用于维护现场的控制状态寄存器和一套独立的TLB访问接口控制寄存器,并且因此TLB重填异常可以在其他异常处理过程中被触发。而当进入TLB重填异常时,硬件会自动设置CSR.CRMD.DA=1和CSR.CRMD.PG=0,即进入直接地址翻译模式,从而避免在TLB重填异常中不能再次产生TLB重填异常。

而如load操作页无效异常等异常,则需要完成类似于page fault的工作。

4、相关指令

在介绍TLB相关异常的处理之前,先对loongarch中相关的指令进行介绍。

(1)TLB异常处理相关指令

具体案例可见后文相关代码分析。

(2)页表遍历相关指令

具体案例可见后文相关代码分析。

5、TLB相关异常处理

下面结合linux源码对TLB相关异常处理进行分析。

linux中TLB相关异常和相关处理函数的对应关系如下:

这里分析handle_tlb_refill、handle_tlb_load和handle_tlb_protect函数。其中handle_tlb_store和handle_tlb_modify实际上流程与handle_tlb_load基本一致,只是更新页表项时更新的位不同。

(1)TLB重填异常

TLB重填异常(handle_tlb_refill)触发前后硬件中的处理与一般异常存在差异,主要是TLB重填异常相关有独立的一套寄存器。但都会有相应保存和恢复现场、跳转和返回操作。值得注意的是,TLB重填异常中出错的地址保存在CSR.TLBRBADV寄存器,而一般异常出错的地址保存在CSR.BADV寄存器。

TLB重填异常的软件处理过程如下:

  1. 保存现场
  2. 根据CSR.TLBRBADV中记录的缺失虚拟地址,和CSR.PGD中pgd基址,遍历发生TLB重填异常的进程的多级页表,从内存中取回页表项信息并填入CSR.TLBELO0和CSR.TLBELO1寄存器的相应域中
  3. 根据填入的CSR.TLBELO0和CSR.TLBELO1寄存器信息,最终用tlbfill指令将页表项填入TLB
  4. 恢复并返回

代码分析如下:

SYM_FUNC_START(handle_tlb_refill)
csrwr t0, LOONGARCH_CSR_TLBRSAVE // 将t0保存到CSR.TLBRSAVE寄存器
csrrd t0, LOONGARCH_CSR_PGD // 读取pgd基址到t0
lddir t0, t0, 3 // 根据CSR.TLBRBADV中记录的缺失虚拟地址,
// 访问3级页表,读取2级页表基址到t0(pgd为3级页表基址)
#if CONFIG_PGTABLE_LEVELS > 3
lddir t0, t0, 2 // 根据CSR.TLBRBADV中记录的缺失虚拟地址,
// 访问2级页表,读取1级页表基址到t0
#endif
#if CONFIG_PGTABLE_LEVELS > 2
lddir t0, t0, 1 // 根据CSR.TLBRBADV中记录的缺失虚拟地址,
// 访问1级页表,读取末级页表地址或大页到t0
#endif
ldpte t0, 0 // 根据CSR.TLBRBADV中记录的缺失虚拟地址,
// 访问末级页表或大页,读取偶数号页表项或大页到CSR.TLBELO0
ldpte t0, 1 // 根据CSR.TLBRBADV中记录的缺失虚拟地址,
// 访问末级页表或大页,读取奇数号页表项或大页到CSR.TLBELO1
tlbfill // 根据CSR.TLBELO0、CSR.TLBELO1等寄存器中信息,
// 将页表项填入TLB
csrrd t0, LOONGARCH_CSR_TLBRSAVE // 恢复t0
ertn // 从异常返回
SYM_FUNC_END(handle_tlb_refill)

(2)load/取指操作页无效异常

load/取指操作页无效异常触发前后硬件中的处理与一般异常相同。

handle_tlb_load处理的过程如下:

  1. 保存现场
  2. 根据CSR.BADV中记录的缺失虚拟地址,和CSR.PGD中pgd基址,遍历发生异常的进程的多级页表,从内存中取回页表项(或大页)信息
  3. 判断该页表项是否存在,如果不存在则会跳转执行缺页处理函数
  4. 如果存在则将页表项置为有效并填入TLB。最后恢复并返回

代码分析如下:

SYM_FUNC_START(handle_tlb_load)
// 将t0、t1、ra写入CSR.SAVE0-CSR.SAVE3,暂存寄存器
csrwr t0, EXCEPTION_KS0
csrwr t1, EXCEPTION_KS1
csrwr ra, EXCEPTION_KS2

// 如果CSR.BADV不小于0,则继续执行到vmalloc_done_load
// 将CSR.BADV和CSR.PGDL读入t0和t1
// 否则跳转到vmalloc_load将CSR.BADV和swapper_pg_dir读入t0和t1
// 即CSR.BADV不小于0时使用低半部分内核地址的pgd,
// 否则使用高半部分用户地址的pgd
csrrd t0, LOONGARCH_CSR_BADV
bltz t0, vmalloc_load
csrrd t1, LOONGARCH_CSR_PGDL
vmalloc_done_load:

// 根据t0中CSR.BADV地址和t1中pgd基址,遍历页表查找
bstrpick.d ra, t0, PTRS_PER_PGD_BITS + PGDIR_SHIFT - 1, PGDIR_SHIFT
alsl.d t1, ra, t1, 3
#if CONFIG_PGTABLE_LEVELS > 3
ld.d t1, t1, 0
bstrpick.d ra, t0, PTRS_PER_PUD_BITS + PUD_SHIFT - 1, PUD_SHIFT
alsl.d t1, ra, t1, 3
#endif
#if CONFIG_PGTABLE_LEVELS > 2
ld.d t1, t1, 0
bstrpick.d ra, t0, PTRS_PER_PMD_BITS + PMD_SHIFT - 1, PMD_SHIFT
alsl.d t1, ra, t1, 3
// 到这里t1中为1级页表(pmd)地址
#endif
// 将1级页表中第一个表项读取到ra
ld.d ra, t1, 0

// 如果ra中表项为大页,则跳转到tlb_huge_update_load
rotri.d ra, ra, _PAGE_HUGE_SHIFT + 1
bltz ra, tlb_huge_update_load

rotri.d ra, ra, 64 - (_PAGE_HUGE_SHIFT + 1)
bstrpick.d t0, t0, PTRS_PER_PTE_BITS + PAGE_SHIFT - 1, PAGE_SHIFT
alsl.d t1, t0, ra, _PTE_T_LOG2
// 到这里t1中为CSR.BADV对应末级页表项地址

// 读取页表项到t0
#ifdef CONFIG_SMP
smp_pgtable_change_load:
ll.d t0, t1, 0 // smp中使用ll/sc原子指令对循环写入
#else
ld.d t0, t1, 0
#endif
// 如果页表项不存在,则跳转到nopage_tlb_load调用缺页处理函数
// 否则继续向下执行,写入对应有效的页表项到TLB
andi ra, t0, _PAGE_PRESENT
beqz ra, nopage_tlb_load

// 设置有效位并更新页表项
ori t0, t0, _PAGE_VALID
#ifdef CONFIG_SMP
sc.d t0, t1, 0
beqz t0, smp_pgtable_change_load // 写入失败时跳转
#else
st.d t0, t1, 0
#endif
// 根据CSR.ASID和CSR.TLBEHI的信息查询TLB,以便tlbwr指令写入
// 如果命中则将其索引写入CSR.TLBIDX,否则将CSR.TLBIDX.NE置为1
// 这里必然会命中
tlbsrch

// t0 = 偶数项页表项,t1 = 奇数项页表项
bstrins.d t1, zero, 3, 3
ld.d t0, t1, 0
ld.d t1, t1, 8
// 写入TLB相关寄存器
csrwr t0, LOONGARCH_CSR_TLBELO0
csrwr t1, LOONGARCH_CSR_TLBELO1
// 根据CSR.TLBELO0、CSR.TLBELO1、CSR.TBLIDX等相关寄存器信息,
// 将页表项信息写入TLB中CSR.TBLIDX.index对应位置
tlbwr
// 恢复并返回
csrrd t0, EXCEPTION_KS0
csrrd t1, EXCEPTION_KS1
csrrd ra, EXCEPTION_KS2
ertn
#ifdef CONFIG_64BIT
vmalloc_load:
la.abs t1, swapper_pg_dir
b vmalloc_done_load
#endif

tlb_huge_update_load:
// 对于大页,异常处理的流程和上面基本页表项的处理流程基本一致
// 只是填入TLB时会做一些额外的格式转换处理等,这里不再赘述
...
nopage_tlb_load:
dbar 0
csrrd ra, EXCEPTION_KS2
la.abs t0, tlb_do_page_fault_0
jr t0
SYM_FUNC_END(handle_tlb_load)

(3)页不可读/不可写/特权不合规异常

页不可读/不可写/特权不合规异常触发前后硬件中的处理与一般异常相同。

handle_tlb_protect处理的过程实际上就是调用缺页处理函数,来填入页表。

代码分析如下:

SYM_FUNC_START(handle_tlb_protect)
// 保存寄存器
BACKUP_T0T1
SAVE_ALL
// 设置传参
move a0, sp
move a1, zero
csrrd a2, LOONGARCH_CSR_BADV
REG_S a2, sp, PT_BVADDR
// 调用do_page_fault
la.abs t0, do_page_fault
jirl ra, t0, 0
// 恢复并返回
RESTORE_ALL_AND_RET
SYM_FUNC_END(handle_tlb_protect)

总结

本文介绍了loongarch架构中软件管理TLB的机制、TLB重填异常和其他TLB相关的异常,以及相应的异常处理和代码分析。

软件管理TLB机制、处理TLB相关异常,算是loongarch架构中TLB相关软件维护中较为特别的地方。下一篇文章将继续介绍loongarch中其他的TLB维护和相关指令。

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

来源:51CTO 开源基础软件社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯