【问题标题】:mmap EINVAL error on UIO deviceUIO 设备上的 mmap EINVAL 错误
【发布时间】:2016-12-24 08:54:38
【问题描述】:

在尝试使用 UIO 而不是直接映射 /dev/mem 后,我在 Xilinx Zynq 上映射物理内存时遇到问题。虽然计划是以普通用户而不是root 身份运行应用程序,但仍以root 身份运行。

显然第一个映射是成功的,而对同一文件描述符 12 (/dev/uio/ps2pl) 的其余映射失败。虽然明显的区别是偏移量,但它在范围内(请参阅设备树)并且页面对齐正确。此应用程序与 /dev/mem 运行良好。

使用strace 运行观察到的错误是:

open("/dev/uio/ps2pl", O_RDWR|O_SYNC)   = 12
open("/sys/bus/i2c/devices/0-0050/eeprom", O_RDONLY) = 13
fstat64(13, {st_mode=S_IFREG|0600, st_size=8192, ...}) = 0
_llseek(13, 0, [0], SEEK_SET)           = 0
read(13, "\1\1\0\0\0\0\0\0", 8)         = 8
read(13, "(\\\217\2(\\\217\00233333333\0\0\0\0\0\0\0\0(\\\217\2(\\\217\2"..., 4096) = 4096
close(13)                               = 0
mmap2(NULL, 48, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0) = 0xb6f93000
mmap2(NULL, 48, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0x400000) = -1 EINVAL (Invalid argument)
mmap2(NULL, 196608, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0x200000) = -1 EINVAL (Invalid argument)
mmap2(NULL, 196608, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0x100000) = -1 EINVAL (Invalid argument)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x1f} ---
+++ killed by SIGSEGV +++
Segmentation fault

加载到内核中的设备树:

# /root/dtc/dtc -f -I fs /sys/firmware/devicetree/base/amba_pl/ps2pl\@40000000/
ERROR (name_properties): "name" property in / is incorrect ("ps2pl" instead of base node name)
Warning: Input tree has errors, output forced
/dts-v1/;

/ {
    reg = <0x40000000 0x40000000>;
    name = "ps2pl";
    interrupts = <0x0 0x44 0x4>;
    compatible = "generic-uio";
    interrupt-parent = <0x3>;
};

UIO 映射的大小足以容纳上述mmap 大小和偏移量:

# cat /sys/devices/soc0/amba_pl/40000000.ps2pl/uio/uio0/maps/map0/size 
0x40000000

【问题讨论】:

    标签: fpga xilinx device-tree zynq


    【解决方案1】:

    mmap 偏移量对/dev/mem 的处理方式与 UIO 设备不同。 不可能使用任意偏移量,而只能映射每个区域的起点。上面的例子在设备树中只定义了一个区域,但是可以定义多个区域:

    reg = <0x40000000 0x10000>,
          <0x40010000 0x10000>,
          <0x40020000 0x10000>,
          <0x40030000 0x10000>;
    reg-names = "region0", "id", "region2", "gpio";
    

    对每个区域/映射的访问并不明显,如下所述: https://lwn.net/Articles/232575/

    访问n-th 区域的偏移量应该是:

    n * sysconf(_SC_PAGESIZE)
    

    在 arm 上,页面大小是 12 位窗口 0x1000

    一些更通用的文档。 http://elinux.org/images/b/b0/Uio080417celfelc08.pdf

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      相关资源
      最近更新 更多