首页 文章

Linux内核使TLB条目无效

提问于
浏览
7

在linux内核中,我编写了类似于 copy_page_range (mm / memory.c)的代码,因此通过COW优化将内存从一个进程复制到另一个进程 . 目标和源地址可以被 PAGE_SIZE 偏移,COW仍然有效 . 但是,我注意到,在用户程序中,当我从相同的源地址复制到不同的目标地址时,TLB似乎没有被正确刷新 . 在高级别,我的用户级代码执行以下操作(我一次只复制一页,我的机器上的0x1000字节):

SRC = 0x20000000

  • 写入SRC(调用关联页面 page1 ) .

  • Syscall将SRC复制到目标进程中的0x30000000 . 现在,src进程地址0x20000000和目标进程地址0x30000000指向同一页面( page1 ) .

  • 写一些与SRC不同的东西(这应该触发页面错误来处理COW) . 假设源地址现在指向 page2 .

  • Syscall将SRC复制到目标进程中的0x30001000 .

此时,应存在两个单独的页面:SRC 0x20000000 page2 DST 0x30000000 page1 DST 0x30001000 page2

我发现在第3步,当我在src 0x20000000中写入不同的内容时,不会生成页面错误 . 检查时,实际页面映射为:SRC 0x20000000 page1 DST 0x30000000 page1 DST 0x30001000 page1

在我的代码中,如果我调用 flush_tlb_page 并传递源地址,则用户代码将按预期使用正确的页面映射 . 所以我确信我没有正确维护TLB . 在 copy_page_range 中,内核在更改页表之前和之后调用 mmu_notifier_invalidate_range_start/end . 我正在做完全相同的事情并进行了双重检查我确实将正确的struct_mm和地址传递给了 mmu_notifier_invalidate_range_start/end . 这个功能不能处理冲洗tlb吗?

好吧,所以字面意思是我输入了这个,我检查了 dup_mmap 并意识到 copy_page_rangedup_mmap (kernel / fork.c)的主调用者调用 flush_tlb_mm . 我猜我应该在我的内核代码之前和之后调用 flush_cache_rangeflush_tlb_range . 它是否正确? mmu_notifier_invalidate_range_start/end 究竟做了什么?

1 回答

  • 9

    是的,如果您正在执行更改页表的操作,则需要确保根据需要使TLB无效 .

    mmu_notifier_invalidate_range_start/end 只是调用MMU通知程序挂钩;这些挂钩只存在,以便在发生TLB失效时可以告知其他内核代码 . 设置MMU通知程序的唯一地方是

    • KVM(硬件辅助虚拟化)使用它们来处理交换页面;它需要知道主机TLB失效,以使虚拟客户MMU与主机保持同步 .

    • GRU(巨大SGI系统中专用硬件的驱动程序)使用MMU通知程序使GRU硬件中的映射表与CPU MMU保持同步 .

    但几乎任何你调用MMU通知程序钩子的地方,如果内核还没有为你做这个,你也应该调用TLB击落功能 .

相关问题