2016-12-24 1 views
0

/dev/mem 대신 직접 UIO를 사용하려고 시도한 후에 Xilinx Zynq에서 실제 메모리를 매핑하는 데 문제가 있습니다. root 대신 일반 사용자로 응용 프로그램을 실행하는 것이 계획이지만 이는 여전히 root으로 실행됩니다.mmap UIO 장치의 EINVAL 오류

분명히 첫 번째 매핑은 성공적이지만 동일한 파일 설명자 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 

커널에로드 같이 장치 트리 다음 UIO 매핑의 크기는 위의 mmap을 수용 할 수있을만큼 큰

# /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>; 
}; 

크기 및 오프셋 :

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

답변

0

mmap 오프셋은 UIO 장치의 경우 /dev/mem에 대해 다르게 처리됩니다. 임의의 오프셋을 사용할 수는 없지만 각 영역의 시작 부분 만 매핑 할 수 있습니다. https://lwn.net/Articles/232575/

오프셋 : 위의 예는 하나 개의 영역을 장치 트리에 정의하지만 복수의 영역을 정의 할 수있다 : 여기에 기술 된 바와 같이 각 영역

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

액세스/매핑은 명확하지 않다 n 번째 영역에 액세스 같아야 페이지 크기를 팔

n * sysconf(_SC_PAGESIZE) 

는 12 비트 윈도우 0x1000이다.

좀 더 일반적인 문서. http://elinux.org/images/b/b0/Uio080417celfelc08.pdf