Documentation/translations/zh_CN/mm/hmm.rst

Source file repositories/reference/linux-study-clean/Documentation/translations/zh_CN/mm/hmm.rst

File Facts

System
Linux kernel
Corpus path
Documentation/translations/zh_CN/mm/hmm.rst
Extension
.rst
Size
19231 bytes
Lines
356
Domain
Support Tooling And Documentation
Bucket
Documentation
Inferred role
Support Tooling And Documentation: documentation
Status
atlas-only

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

CPU pte 没有设置写权限,那么HMM将调用handle_mm_fault()。

hmm_range_fault 完成后,标志位被设置为页表的当前状态,即 HMM_PFN_VALID | 如果页
面可写,将设置 HMM_PFN_WRITE。


从核心内核的角度表示和管理设备内存
==================================

尝试了几种不同的设计来支持设备内存。第一个使用特定于设备的数据结构来保存有关迁移内存
的信息,HMM 将自身挂接到 mm 代码的各个位置,以处理对设备内存支持的地址的任何访问。
事实证明,这最终复制了 struct page 的大部分字段,并且还需要更新许多内核代码路径才
能理解这种新的内存类型。

大多数内核代码路径从不尝试访问页面后面的内存,而只关心struct page的内容。正因为如此,
HMM 切换到直接使用 struct page 用于设备内存,这使得大多数内核代码路径不知道差异。
我们只需要确保没有人试图从 CPU 端映射这些页面。

移入和移出设备内存
==================

由于 CPU 无法直接访问设备内存,因此设备驱动程序必须使用硬件 DMA 或设备特定的加载/存
储指令来迁移数据。migrate_vma_setup()、migrate_vma_pages() 和
migrate_vma_finalize() 函数旨在使驱动程序更易于编写并集中跨驱动程序的通用代码。

在将页面迁移到设备私有内存之前,需要创建特殊的设备私有 ``struct page`` 。这些将用
作特殊的“交换”页表条目,以便 CPU 进程在尝试访问已迁移到设备专用内存的页面时会发生异常。

这些可以通过以下方式分配和释放::

    struct resource *res;
    struct dev_pagemap pagemap;

    res = request_free_mem_region(&iomem_resource, /* number of bytes */,
                                  "name of driver resource");
    pagemap.type = MEMORY_DEVICE_PRIVATE;
    pagemap.range.start = res->start;
    pagemap.range.end = res->end;
    pagemap.nr_range = 1;
    pagemap.ops = &device_devmem_ops;
    memremap_pages(&pagemap, numa_node_id());

    memunmap_pages(&pagemap);
    release_mem_region(pagemap.range.start, range_len(&pagemap.range));

还有devm_request_free_mem_region(), devm_memremap_pages(),
devm_memunmap_pages() 和 devm_release_mem_region() 当资源可以绑定到 ``struct device``.

整体迁移步骤类似于在系统内存中迁移 NUMA 页面(see Documentation/mm/page_migration.rst) ,
但这些步骤分为设备驱动程序特定代码和共享公共代码:

1. ``mmap_read_lock()``

   设备驱动程序必须将 ``struct vm_area_struct`` 传递给migrate_vma_setup(),
   因此需要在迁移期间保留 mmap_read_lock() 或 mmap_write_lock()。

2. ``migrate_vma_setup(struct migrate_vma *args)``

   设备驱动初始化了 ``struct migrate_vma`` 的字段,并将该指针传递给
   migrate_vma_setup()。``args->flags`` 字段是用来过滤哪些源页面应该被迁移。
   例如,设置 ``MIGRATE_VMA_SELECT_SYSTEM`` 将只迁移系统内存,设置
   ``MIGRATE_VMA_SELECT_DEVICE_PRIVATE`` 将只迁移驻留在设备私有内存中的页
   面。如果后者被设置, ``args->pgmap_owner`` 字段被用来识别驱动所拥有的设备
   私有页。这就避免了试图迁移驻留在其他设备中的设备私有页。目前,只有匿名的私有VMA
   范围可以被迁移到系统内存和设备私有内存。

   migrate_vma_setup()所做的第一步是用 ``mmu_notifier_invalidate_range_start()``
   和 ``mmu_notifier_invalidate_range_end()`` 调用来遍历设备周围的页表,使
   其他设备的MMU无效,以便在 ``args->src`` 数组中填写要迁移的PFN。
   ``invalidate_range_start()`` 回调传递给一个``struct mmu_notifier_range`` ,

Annotation

Implementation Notes