我面临着CMA的问题。我正在尝试通过CMA(连续内存分配)为运行linux 3.8内核的基于ARM的目标板分配设备内存。
在通过私有cma节点请求内存分配时,它会产生“NO memin CMA area”。尽管我们保留了所需的内存。在调试“_alloc_contig_migrate_range”函数时,我们发现某些页面的迁移失败并导致CMA区域中没有mem。
正在迁移满足“migrate_page_move_mapping(migrate.c)”功能中的以下条件的页面。
if (!mapping) {
/* Anonymous page without mapping */
if (page_count(page) != 1) {
return -EAGAIN;
}
return MIGRATEPAGE_SUCCESS;
}
其他页面失败并从migrate_page_move_mapping()返回
if (page_count(page) != expected_count ||
radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {
spin_unlock_irq(&mapping->tree_lock);
return -EAGAIN;
}
而page_count(页) - > 3和预期计数 - > 2不匹配,因此重复返回-EAGAIN。
在查看页面标志时,我发现了标志中的差异。
迁移成功 - > 0xc3a40059
迁移失败 - > 0xc3a0000d
标志中的差异是
观察标志 - > PG_dirty PG_active PG_swapbacked PG_referenced
迁移成功----> SET SET SET NOTSET
迁移失败------> NOTSET NOTSET NOTSET SET
任何建议都会有所帮助。
记录了为什么CMA迁移可能在早于3.18的内核上失败的几个原因 here(伙伴分配器会计错误)和here(不支持KSM迁移)。
与流行的看法相反,Linux内核中的Contiguous Memory Allocator框架 并不保证在整个系统生命周期内连续内存的可用性。
CMA的核心概念如下......
问题在于在某些情况下, 在步骤3a中迁移页面可能会失败。这可能是由于:
由于在更新/替换CMA的单一方法上没有任何理由,它在大多数时间以其当前形式继续存在,但在所有可能的情况下都不能保证连续的存储。随着SMMU的出现和对其他控制器的分散 - 聚集DMA支持,对较大的连续缓冲区的需求较少。
也就是说,有两种主要方法可以改进CMA,这些方法已经尝试过并在某些圈子中被接受:
基于他们认为可接受的妥协,这两种方法都有其自身的局限性。