X86 串行端口的mmap IO端口地址
我正在检查串行端口(uart)0x2f8的io端口地址是否可以映射到用户空间。 我想自己在驱动程序中实现这一点,而不是使用任何库来知道需要哪些api来实现这一点。然而,鉴于这是x86和端口IO特定的,我不确定它是否真的可以实现。不管怎样,我已经在用户空间中编写了一个mmap函数和调用者X86 串行端口的mmap IO端口地址,x86,linux-device-driver,embedded-linux,kernel-module,X86,Linux Device Driver,Embedded Linux,Kernel Module,我正在检查串行端口(uart)0x2f8的io端口地址是否可以映射到用户空间。 我想自己在驱动程序中实现这一点,而不是使用任何库来知道需要哪些api来实现这一点。然而,鉴于这是x86和端口IO特定的,我不确定它是否真的可以实现。不管怎样,我已经在用户空间中编写了一个mmap函数和调用者 Setting up the mapping is as below: res=请求区域(基本地址,8,“自定义串行设备”); void\uuu iomem*mem\u base\u addr=ioport\u
Setting up the mapping is as below:
res=请求区域(基本地址,8,“自定义串行设备”);
void\uuu iomem*mem\u base\u addr=ioport\u map(base\u addr,8);
iowrite8(0x01,(u8*)我的开发->内存基本地址+3)/*没有更多的配置和工作良好*/
/*在此之后,我能够使uart功能在软件环回模式*/
现在我决定在这个地址上尝试mmap:
static int my_dev_mmap(struct file*filep,struct vm_area\u struct*vma){
串行设备*我的设备=(串行设备*)文件P->私有设备数据;
无符号长pfn;
size_t sz=vma->vm_end-vma->vm_start;
无符号长物理地址;
if(vma->vm_end-vma->vm_start!=页面大小){
返回-艾因瓦尔;
}
如果(页面大小>(1个vm\u页面保护=pgprot\u未缓存(vma->vm\u页面保护);
vma->vm|U标志|=vm|U IO;
/*ioport_映射提供了虚拟地址,所以我在下面使用它来获取物理地址*/
phys_addr=virt_to_phys(my_dev->mem_base_addr);
pfn=物理地址>>页面移位;
printk(“GNA:mmap调用:vm开始:0x%lx vm结束:0x%lx内存库:0x%lx物理:0x%lx pfn:%lu\n”,
vma->vm_开始,vma->vm_结束,(未签名长)my_dev->mem_base_addr,phys_addr,pfn);
if(重新映射pfn_范围(vma、vma->vm_开始、pfn、sz、vma->vm_页面保护)){
printk(“GNA:mmap失败\n”);
返回-伊根;
}
返回0;
}
我得到的打印结果如下:
Dec 19 11:05:00 realtek-dpdk kernel: [ 4624.894086] GNA: mmap called:
vm-start: 0x7fa150f4d000 --> Kernel allocates this range which is in user space
vm-end: 0x7fa150f4e000
mem_base: 0x102f8
phys: 0x6587800102f8 --> Virt_to_phys gave this which seems wrong
pfn: 27254063120
当我打印mmap的内存时,我期望0x5A位于0x2f8(uart的基)的偏移量0x7(便笺簿)处。但是我没有看到预期的输出
我尝试过的另一种方法是,ioport_map给出了一个地址0x102f8,这似乎不正确
类似于虚拟地址,但更多的是物理地址(BASE+0x2f8)
所以,我直接用这个地址得到了pfn,但结果还是一样的
我的用户空间程序如下所示:
address=mmap(空,页面大小,保护读取,保护写入,映射共享,配置fd,0);
在这之后,我试图找到写在暂存器内存中偏移量0x7处的值
for(int i=0;i<10;i++){
printf(“值:0x%x 0x%x\n”,地址[i],地址[0x2f8+i]);
}
因此,是否可以mmap()
ioport。如果可以,请告诉正确的步骤
PS:虽然这是x86,但我添加了嵌入式linux标记,以便从平台端获得一些帮助,以防有人知道其中的区别。注意:这个答案是针对x86的 通过输入和输出指令访问I/O端口 应该可以mmap一个由驱动程序管理的跳出缓冲区,并使用这些指令将其写入串行。您可能需要编写一个同步接口(例如刷新ioctl) 与基于MMIO的设备不同,您无法粗略地直接将与设备接触的内存映射到用户空间,因为该内存不存在
您可以尝试破坏I/O端口权限,以便用户空间能够访问I/O端口本身管理它。@rutherford明白了,io端口没有底层结构页,因此无法进行MMAP,如果我尝试根据io地址计算PFN并使用它,它会损坏其他一些有效内存。我想知道ioport\u map在MMIO地址空间中创建页面或映射方面是否有任何作用,因为在ioport\u map之后,我能够完美地使用ioread()和iowrite()MMIO指令。不,不可能将I/O映射到虚拟地址空间。请阅读
ioread()
和iowrite()
的实现以获得技巧(是的,您注意到地址只是0x10000+I/O端口,这是在中途,很明显,为什么-I/O空间是16位宽的,这个地址只是第一个不与端口偏移重叠的地址)。是的,这只是x86,在其他体系结构上没有I/O端口的概念。