免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 枫露清愁
打印 上一主题 下一主题

[内核模块] 内存映射内核和用户读写数据不同步 [复制链接]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
11 [报告]
发表于 2014-09-11 15:34 |只看该作者
    dma_map_single和dma_unmap_single这两个函数就是用来clean/invalid cache的
如果闲麻烦,用上面的方法2就行了,方法2是最简单的

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
12 [报告]
发表于 2014-09-12 08:41 |只看该作者
回复 1# 枫露清愁

写完以后flush_cache_all()一下就行了。
其实调用dma_map_single也就是想flush_cache一下而已,本身不是DMA,没有必要调用这种大的一个函数。


   

论坛徽章:
0
13 [报告]
发表于 2014-09-12 09:10 |只看该作者
谢谢大家的帮助,我在内核写完数据之后调用了flush_dcache_page刷新了一些对应的页,应用层再去读就会正确了,测试了一个晚上也没出问题,但如果读写很频繁,这样会不会太影响效率?

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
14 [报告]
发表于 2014-09-12 09:22 |只看该作者
回复 13# 枫露清愁
典型又想马不吃草,又想马跑得好型。


   

论坛徽章:
0
15 [报告]
发表于 2014-09-12 09:30 |只看该作者
回复 14# Tinnal
我的意思是有没有更好的方法来避免此类问题了

   

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
16 [报告]
发表于 2014-09-12 20:25 |只看该作者
本帖最后由 arm-linux-gcc 于 2014-09-12 20:32 编辑

ARM9硬件限制,所以无法避免这种问题,是由于vivt类型的cache导致的

要想避免这种问题,并且还要兼顾高性能,那么要用ARM11或cortex-a系列的
cache必须是vipt或pipt的,此时app和kernel都不用关cache

vipt类型的cache,app和kernel都不关cache,那么必须要让app知道物理地址,然后mmap时pgoff要传递正确的pfn给内核,否则会有alias的问题
pipt类型的cache就随便折腾了,只要两边都打开cache就不会有问题




论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
17 [报告]
发表于 2014-09-13 00:05 |只看该作者
@arm-linux-gcc@枫露清愁

以前真没留意cache的地址转换模式问题,被你这一说,回来恶补了一下。

1. 对于正常的应用,VIVT是效率最高的。因此不能因为这个特殊需求把整体的性能都降下来了。
2. VIPT的方式只解决了homonyms问题,不能解决aliasing问题。而楼主的问题,主要是aliasing问题导致。因此只有PIPT模式能真正的解决这个问题,但这也是cache最低效率的用法!

相关的结论来自对如下资料Address translation章节的分析:
http://en.wikipedia.org/wiki/CPU_cache

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
18 [报告]
发表于 2014-09-13 11:32 |只看该作者
本帖最后由 arm-linux-gcc 于 2014-09-13 12:15 编辑

回复 17# Tinnal


    vipt alias问题可以通过page color来解决,linux实现了page color的
arm手册上也明确写了vipt aliasing的data cache的解决方法——page color

vipt又分为aliasing和nonaliasing两种:
前者需要软件来解决alias的问题,方法就是page color。
后者硬件能够解决,硬件会扫一遍与当前line可能发生alias的那些所有line,以避免同一个pa出现在不同的line中,于是从逻辑上看上去就好像way size小于等于page size。



使用vipt的cache,做mmap时要特别注意pgoff参数,这个参数一定要使用正确的pfn,而不能传一个NULL进去



x86 powerpc arm的cortex-a系列都是pipt,随着技术的发展,mmu tlb的命中率更高了,pipt相比vivt性能并不会低太多,
然而最重要是pipt在smp系统中、不同core的cache之间的一致性的处理比viXt更好更快,从cpu的综合性能看来pipt比viXt更适合现代cpu一些。

老mips是vipt,较新的mips不知道是啥









linux page color,用于解决vipt data cache aliasing的问题,原理如下:

让va和pa之间的差值为16K的整数倍,因为arm架构规定了vipt cache最大way size为16K,
所以对于同一个pa来说、至多会有4个line可能存在alias,在内核中有#define SHMLBA (4 * PAGE_SIZE)。

做mmap时内核会选一个va来映射到已知的pa,而选择的原则就是va pa差值必须为16K的整数倍,
于是不同va映射到同一个pa时,va之间也能够满足差值为16K整数倍,于是cpu在寻址cache line时,这两个不同的va最终可以落在同一个set中,
然后在这个set的几个line中,最终会发现有一个line的pt与自己符合,
于是最终这两个差值为16K整数倍的不同va能够命中同一个line。

所以我才会在前面说mmap时一定要传递正确的pgoff,因为pgoff会用来选择一个va。





论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
19 [报告]
发表于 2014-09-13 19:45 |只看该作者
回复 18# arm-linux-gcc

恩,回贴时只看了wiki, 没有去研究代码,ARM Linux对cache alias 确实在软件层面做了处理,令虚拟地址的index一致。在如下代码里arch_get_unmapped_area里就有反映。
  1. #ifdef CONFIG_CPU_V6
  2.         unsigned int cache_type;
  3.         int do_align = 0, aliasing = 0;

  4.         /*
  5.          * We only need to do colour alignment if either the I or D
  6.          * caches alias.  This is indicated by bits 9 and 21 of the
  7.          * cache type register.
  8.          */
  9.         cache_type = read_cpuid(CPUID_CACHETYPE);
  10.         if (cache_type != read_cpuid(CPUID_ID)) {
  11.                 aliasing = (cache_type | cache_type >> 12) & (1 << 11);
  12.                 if (aliasing)
  13.                         do_align = filp || flags & MAP_SHARED;
  14.         }
  15. #else
  16. #define do_align 0
  17. #define aliasing 0
  18. #endif
复制代码
在文件映射或MAP_SHARED共享映射下,都会对返回的虚拟地下做颜色对齐。
要对cache深入了解了不少。{:3_189:}


另外,X86应该是属于VIPT的吧。X86的手册上浏览了一下,没有直接的说明,但下如的网页里有描述:
http://stackoverflow.com/questio ... 64-for-caching-in-t
http://www.motherboardpoint.com/ ... hes-and-mmu.152345/
不知arm-linux-gcc兄能不能找到官方的出处呢。

PPC家里没有手册,没法查。

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
20 [报告]
发表于 2014-09-13 20:31 |只看该作者
但发现一个问题,就是Linux会做这个color对齐动作的只在用户态的mmap操作里进行。对内核代码分配出来的内存(包括slab\buddy)就没有这么幸运了,因为内核地址都是线性映射的,做color的对齐操作会出现大量的内存浪费,因此内核分配的地址,只能让内核开发者自己去保证了。vmalloc也没能难逃厄运{:3_184:} 。而楼主这个场景,推测内核就是由内核分配的。
反观内核目前的代码,在内核里头我们经常看到flush cache操作,但在用户态反倒可以不在意cache的问题,从这来看就能于通了。因为文件映射和共享映射都解决了cache alias的问题了。
呵呵,因此结论是,还是老老实实去flush吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP