直接内存映射到DIMM

5
假设您在一个 Intel x86-64 主板上插入了 2 个 DIMM。所有内存交错(bank 和 channel)都已禁用。
我想要做的是从 Linux kernel(版本 4.11.11)中保留其中一个 DIMM 的物理内存空间,并将该物理(保留)内存空间暴露给应用程序。DIMMs 将不会在内存通道中移动。我该如何做?这个过程是什么?我是内核开发新手,需要指导。
目前我找到的资料如下:
  1. 要从Linux内核中保留内存,您可以指定memmap=nn[KMG]$ss[KMG]启动参数。该参数将特定的内存标记为从ss到ss+nn的内存保留区域。

  2. mmap可用于在进程的地址空间中建立一个映射,将地址pa处的len字节与文件描述符fildes表示的内存对象在偏移量off处的len字节相关联。

预留内存后,我假设需要某些字符设备驱动程序将保留的内存暴露给用户空间应用程序?有什么想法吗?


更新

需要保留的DIMM将位于其专用内存通道中,并且不会启用任何银行或通道交错。


我不确定在发现物理地址映射到DIMMs方面是否有很好的支持。通常,BIOS会进行配置,并且一些BIOS(特别是服务器)将允许您选择交错参数。我不知道粒度通常是多少;如果小于2MiB,您将无法使用巨型页面,这可能比您希望从中获得的任何东西都更糟糕。 - Peter Cordes
1
@PeterCordes 感谢您的评论。我添加了一些更新。在服务器平台上,将禁用内存银行和通道交错,并且必须保留的DIMM将位于其自己的专用通道中。在内存通道中不会存在其他DIMM。我正在尝试一些预取机制,带宽是我的目标。您有什么想法? - Jonathan
1
好的,这听起来是一个想要这样做的好理由,但我不确定它能否有效。硬件预取并不考虑内存通道,只考虑L2和L3之间的管道有多忙,或者其他情况。所以如果管道已经充满了对另一个通道的存储操作,那么对你正在测试的通道的预取可能就不会发生。(另一方面,大部分Intel CPU中的预取硬件都在L2中,而L2是每个核心私有的。我不确定来自其他核心的流量对限制预取有多大影响。)如果你能安排一个大部分空闲的系统进行测试,那将会更容易很多。 - Peter Cordes
@PeterCordes 我明白这可能不会比当前可行的带宽更好。这是为了实验性研究来测试一些替代方案。我不指望能超过当前的带宽能力。 - Jonathan
@PeterCordes 谢谢您的澄清。 回到我的原始问题,一个人应该如何从Linux内核中预留与那个DIMM相关联的内存? 最好的方法是什么? - Jonathan
显示剩余6条评论
1个回答

1

映射/dev/mem是一种简单的方法。我以前做过这个。它的mmap实现来自于内核源代码

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;
}

唯一需要修改的是valid_mmap_phys_addr_range(vma->vm_pgoff, size)。或者你可以编写自己的/dev/mem驱动程序版本。

但是这并不会分配/保留那些物理内存区域,以防止它们被用于其他任何目的,对吗?而将其映射为VM_IO,会有什么影响,正如该注释所示?mmap(/dev/mem)很可能是完整答案的一个有用部分,但我认为这部分并不是难点。 - Peter Cordes
使用mem=xx命令行参数可以让内核只使用部分内存。例如,传递mem=4G将使内核只使用4G以下的内存,然后您可以使用修改过的/dev/mem驱动程序来映射4G以上的内存。 - Chris Tsui
这是一个有趣的想法,对于OP的设置应该可以工作而不需要交错。你确定/dev/mem仍然可以访问内存范围之外的内存吗? - Peter Cordes
1
不,你不能直接使用/dev/mem来达到你的目标。正如我所发表的,你应该对地址检查进行一些修改。 - Chris Tsui

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接