功能remap_pfn_range
将您的虚拟内存区域指定为special
通过使用pte_mkspecial
并包括VM_IO/VM_PFNMAP
在VMA中。因此,它无法通过特定验证Direct I/O
.
既然你的记忆来自于CMA
已经支持struct page
,你可以利用vm_insert_pages
通过以下步骤:
- Add
CMA
使用内核参数或设备树源的区域(DTS
).
- 从 CMA 获取结构页:
dma_page = dma_alloc_contiguous(&pdev->dev, size, GFP_KERNEL);
if (!dma_page) {
pr_err("%s %d, dma_alloc_contiguous fail\n", __func__, __LINE__);
return -ENOMEM;
}
nr_pages = DIV_ROUND_UP(size, PAGE_SIZE);
pages = kvmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL);
for (i = 0; i < nr_pages; i++)
pages[i] = &dma_page[i];
- 调用时将页面插入vma
mmap
:
int your_mmap(struct file *file, struct vm_area_struct *vma) {
int ret = 0;
unsigned long temp_nr_pages;
if (vma->vm_end - vma->vm_start > size)
return -EINVAL;
/* Duplicate nr_pages as vm_insert_pages can change nr_pages */
temp_nr_pages = nr_pages;
ret = vm_insert_pages(vma, vma->vm_start, pages, &temp_nr_pages);
if (ret < 0)
pr_err("%s vm_insert_pages fail, error is %d\n", __func__, ret);
return ret;
}
- Export
dma_alloc_contiguous
(唯一的内存管理代码发生了变化,但这是可以接受的)。
modified kernel/dma/contiguous.c
@@ -332,6 +332,7 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
return cma_alloc_aligned(dma_contiguous_default_area, size, gfp); }
+EXPORT_SYMBOL(dma_alloc_contiguous);
/**
* dma_free_contiguous() - release allocated pages