Memory 直接内存映射到DIMM

Memory 直接内存映射到DIMM,memory,memory-management,linux-kernel,x86-64,Memory,Memory Management,Linux Kernel,X86 64,假设您将2个DIMM插入英特尔x86-64主板。禁用所有内存交错(存储组和通道) 我试图做的是从Linux内核(版本4.11.11)中保留其中一个DIMM的物理内存空间,并为应用程序公开该物理(保留)内存空间。DIMM将不会在内存通道中移动。我该怎么做呢?这个过程是什么?我是内核开发新手,可以使用指导 到目前为止,我发现: 要从Linux内核保留内存,可以指定memmap=nn[KMG]$ss[KMG]boot参数。此参数将特定内存标记为从ss到ss+nn的内存保留区域 可用于在len字节的地址

假设您将2个DIMM插入英特尔x86-64主板。禁用所有内存交错(存储组和通道)

我试图做的是从
Linux内核
(版本
4.11.11
)中保留其中一个DIMM的物理内存空间,并为应用程序公开该物理(保留)内存空间。DIMM将不会在内存通道中移动。我该怎么做呢?这个过程是什么?我是内核开发新手,可以使用指导

到目前为止,我发现:

  • 要从Linux内核保留内存,可以指定
    memmap=nn[KMG]$ss[KMG]
    boot参数。此参数将特定内存标记为从ss到ss+nn的内存保留区域

  • 可用于在len字节的地址pa处的进程地址空间与len字节的偏移量为offset的文件描述符fildes表示的内存对象之间建立映射

  • 在内存被保留之后,我假设需要一些字符设备驱动程序来向用户空间应用程序公开保留的内存?想法


    更新


    还应注意,需要保留的DIMM将位于其自己的专用内存通道中,并且不会启用存储组或通道交错。

    映射
    /dev/mem
    是一种简单的方法。我以前做过这件事。
    mmap
    从以下位置执行:

    static int mmap_mem(结构文件*文件,结构vm_区域_结构*vma)
    {
    size\u t size=vma->vm\u end-vma->vm\u start;
    
    物理地址偏移量=(物理地址)vma->vm_pgoff我看不出DIMM部分如何融入整个画面。无论如何,像
    /dev/mem
    这样的东西不是吗?我不知道这样的设备是否会映射保留的内存。@MargaretBloom DIMM有什么不清楚的地方?我正试图保留其中一个DIMM上的所有内存,不让内核使用。清楚吗?
    >/dev/mem
    表示内核可使用的所有内存,因此不一定代表我需要的内存。您可以通过
    mmap
    的新标志将其公开,即定义
    MAP\u RESERVED\u DIMM
    ,如果标志arg中有任何未使用的位。HugeTLBFS是另一种模型:一种特殊的文件系统,您可以n将文件映射到备份内存上,以获得一些特殊的映射。我不是Linux内部技术专家(只是一个感兴趣的业余爱好者),但您对字符或块设备的想法可能也适用。特别是如果您一次只计划使用一个用户空间进程,否则您如何让他们知道哪些部分已经映射?@PeterCordes感谢您的评论。我添加了一些更新。内存库和通道交错将在服务器平台中禁用,而必须保留的DIMM将位于其自己的专用通道中。内存通道中不会有其他DIMM。我正在试验一些预取机制,带宽是我的目标。想法?好吧,这听起来是想要这样做的一个很好的理由,但我不确定它是否能正常工作。硬件预取不会占用内存考虑到管道在L2和L3之间的繁忙程度,或者其他任何情况。因此,如果它对另一个通道充满存储,则可能不会对正在测试的通道进行预回迁。(OTOH,Intel CPU中的大多数预取硬件都在L2中,每个内核都是私有的。我不确定来自其他内核的流量对节流预取有多大影响。)如果你能安排的话,在一个大部分空闲的系统上进行测试会容易得多。但这不会分配/保留那些物理内存区域来阻止它们被用于其他任何事情,是吗?正如注释所示,将其映射为
    VM_IO
    会有什么影响?mmap(/dev/mem)可能是完整答案中有用的一部分,但我不认为这部分是困难的一部分。使用
    mem=xx
    cmdline使内核只使用部分内存。例如,传递
    mem=4G
    将使内核只使用4G以下的内存,然后可以使用修改后的
    /dev/mem
    驱动程序将内存映射到4G以上。这是一个有趣的问题你确定
    /dev/mem
    仍然可以访问内核其他部分认为存在的范围之外的内存吗?不,你不能直接使用
    /dev/mem
    来实现你的目标。正如我所说的,你应该对地址检查做一些修改。
    static int mmap_mem(struct file *file, struct vm_area_struct *vma)
    {
        size_t size = vma->vm_end - vma->vm_start;
        phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
    
        /* It's illegal to wrap around the end of the physical address space. */
        if (offset + (phys_addr_t)size - 1 < offset)
            return -EINVAL;
    
        if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
            return -EINVAL;
    
        if (!private_mapping_ok(vma))
            return -ENOSYS;
    
        if (!range_is_allowed(vma->vm_pgoff, size))
            return -EPERM;
    
        if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
                            &vma->vm_page_prot))
            return -EINVAL;
    
        vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
                             size,
                             vma->vm_page_prot);
    
        vma->vm_ops = &mmap_mem_ops;
    
        /* Remap-pfn-range will mark the range VM_IO */
        if (remap_pfn_range(vma,
                    vma->vm_start,
                    vma->vm_pgoff,
                    size,
                    vma->vm_page_prot)) {
            return -EAGAIN;
        }
        return 0;
    }