免费注册 查看新帖 |

Chinaunix

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

kernel 中如何访问管理pci memory [复制链接]

论坛徽章:
0
61 [报告]
发表于 2009-04-19 16:57 |只看该作者
关于a版主提到的是否存在多个虚拟地址对1个物理地址的问题,我写了个小测试程序,高手勿笑.

#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cache.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <asm/page.h>
#include <asm/uaccess.h>

static int __init mm_test(void){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void *pa = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void *va1 = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void *va2 = kmalloc(16, GFP_KERNEL);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!va2)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR"va2 is %p\n", va2);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa =(void *) __pa(va2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR"pa is %p\n", pa);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;va1 = ioremap((unsigned long)pa, (unsigned long)16);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!va1){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR"ioremap error\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kfree(va2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR"va1 is %p\n", va1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strncpy(va1, "double va test\n", 16);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR"%s\n", (char *)va2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iounmap(va1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kfree(va2);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}
static void __exit mm_exit(void){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
}

module_init(mm_test);
module_exit(mm_exit);
MODULE_LICENSE("GPL");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


平台是32位arm.
运行后打出来的信息如下:
insmod mmtest.ko
va2 is c1761ac0
pa is 01761ac0
va1 is c2878ac0
double va test

[ 本帖最后由 epegasus 于 2009-4-19 18:42 编辑 ]

论坛徽章:
0
62 [报告]
发表于 2009-04-19 19:57 |只看该作者
原帖由 epegasus 于 2009-4-19 16:05 发表
>>内核中可以访问所有的物理页面,换而言之所有的物理页面在系统空间都有映射.

这个貌似有问题.
物理内存地址大于HIMEM的时候开始只在低端内存在保存了它们的page信息.
高端内存只在有需要的时候映射,可以 ...


64位x86就不需要高端内存了吧?

论坛徽章:
0
63 [报告]
发表于 2009-04-19 20:19 |只看该作者
原帖由 epegasus 于 2009-4-19 16:05 发表
>>内核中可以访问所有的物理页面,换而言之所有的物理页面在系统空间都有映射.

这个貌似有问题.
物理内存地址大于HIMEM的时候开始只在低端内存在保存了它们的page信息.
高端内存只在有需要的时候映射,可以 ...



我们讨论的也是基于0-896M物理内存的情况, 情景分析中没有指明。

论坛徽章:
0
64 [报告]
发表于 2009-04-19 20:31 |只看该作者
原帖由 epegasus 于 2009-4-19 16:57 发表
关于a版主提到的是否存在多个虚拟地址对1个物理地址的问题,我写了个小测试程序,高手勿笑.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include  ...


其实例子可以在head.S中找到,在切换到virtual address mode的时候,为了保证切换之后地址访问的连续性,0-8M和c00000000-c0000000+8M虚拟地址都会映射到0-8M的物理地址。不过这个例子只是说明可以映射 并不代表内核也是这么做的

[ 本帖最后由 javacool 于 2009-4-19 21:11 编辑 ]

论坛徽章:
0
65 [报告]
发表于 2009-04-20 00:40 |只看该作者
恩,是便于管理的考虑。在 NT KERNEL 中的只有在 0x80000000 -> 0xA0000000 之间
的虚拟地址才有可能减去一个 OFFSET 得到物理地址。内存管理这块总体来说与 LINUX 还是
有挺大差别的。

CPU 寻址的时候依然是查表操作,它不会管内核怎样实现。所有这些应该都是内核为了管理与
效率上的考虑。

还有,关于“多个虚拟地址对应一个物理地址的问题”,不知是我没有理解各位的意思,还是
漏看了什么讨论过程,没有结合到上下文?单从这个问题来看,我觉得这不是典型的 Lazy
Evaluation 机制么?这种手法在现代 OS 中应该随处可见啊。尤其是 COPY ON WRITE
这种典型的应用。如像共享库,实际只加载一份,不同进程共享,指向相同的物理页面,保证读
取时的正确性,只有在某个进程写的时候才为其分配新的物理页面。

论坛徽章:
0
66 [报告]
发表于 2009-04-20 08:06 |只看该作者
a版主的意思应该是在同一个页表中 ls说的情况是两个不同页表的映射同一个物理地址

论坛徽章:
0
67 [报告]
发表于 2009-04-21 11:53 |只看该作者
搞定

论坛徽章:
0
68 [报告]
发表于 2009-04-21 17:44 |只看该作者
原帖由 eexplorer 于 2009-4-16 20:13 发表
> 1) 这部分物理内存, 若要映射到内核, 必是加上一个PAGE_OFFSET这么简单的映射;
> 2) 但是, 内核并一开始就为所有这样的物理内存永久的建立了这种映射。

那请问,kernel什么时候会建立这样映射?加上 ...



完整看了一遍所有的帖子: 关于是否映射到内核空间, 您说的对, 我理解的有问题。  (现在太懒了,搁以前应该好好看看代码,充充电)

关于内核如何访问用户空间虚拟地址,我说的对,您起初的理解有问题。

论坛徽章:
0
69 [报告]
发表于 2009-04-21 18:09 |只看该作者
原帖由 albcamus 于 2009-4-21 17:44 发表



完整看了一遍所有的帖子: 关于是否映射到内核空间, 您说的对, 我理解的有问题。  (现在太懒了,搁以前应该好好看看代码,充充电)

关于内核如何访问用户空间虚拟地址,我说的对,您起初的理解有问题。


是的,关于内核访问用于空间虚拟地址,由于一开始我就看了__copy_to_user_ll()这个函数,受了误导,所以以为都是通过get_user_pages来实现的。由于你的提醒,我看了一下x86的ASM code, 一般是在user process context中,kernel直接拿user process 的虚拟地址直接访问。

但是在某些情况下(比如aio),我觉得,kernel会在user process contex下先通过get_user_pages()得到user pages,然后在kernel thread中访问这个user page的话,还是通过kernel virtual address访问。need to check aio code...

论坛徽章:
0
70 [报告]
发表于 2009-04-22 16:32 |只看该作者
学习中
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP