2013-06-04 8 views
2

소개 :리눅스 커널 flush_cache_range는() 호출은 아무것도를하지 않는다 보인다

우리는 리눅스는 ARM에서 실행되는 응용 프로그램이 외부 프로세서에서 데이터를 받아 가지고있는 ARM의 메모리 공간에있는 DMA의 데이터. 그런 다음 ARM은 사용자 모드 코드에서 해당 데이터에 액세스해야합니다.

외부 프로세서의 DMA 엔진이 분산/수집을 지원하지 않으므로 주소 범위는 물리적으로 인접해야합니다. 이 메모리 범위는 처음에 __get_free_pages (GFP_KERNEL | __GFP_DMA, order) 호출을 통해 ARM 커널에서 할당되므로 할당 된 메모리가 물리적으로 인접 해 있음을 보장합니다. 그런 다음 반환 된 포인터에 대한 virt_to_phys() 호출은 프로세스 시작시 외부 프로세서에 제공되는 실제 주소를 제공합니다.

이 실제 주소는 (사용자 모드에서)이 메모리 영역에 대한 사용자 모드 포인터를 얻기 위해 mmap() API를 호출하는 Linux 사용자 모드 코드에도 알려져 있습니다. 그런 다음 Linux 커널 드라이버는 드라이버의 file_operations 구조에서 해당 mmap 루틴을 호출합니다. 드라이버는 나중에 사용하기 위해 mmap 루틴을 호출 할 때 vm_area_struct "vma"포인터를 전달합니다.

새로운 데이터가이 메모리 주소로 DMA되었다는 신호를 사용자 모드 코드가 받으면 위에서 언급 한 mmap() 호출에서 얻은 사용자 모드 포인터를 통해 사용자 모드에서 액세스해야합니다. 물론 사용자 모드 코드가이를 수행하기 전에이 메모리 범위에 해당하는 캐시를 플러시해야합니다. 이 플러시를 수행하기 위해 사용자 모드 코드는 드라이버를 (ioctl을 통해) 호출하고 커널 모드에서는 flush_cache_range() 호출을 수행합니다.

flush_cache_range (vma, start, end);

위의 호출에 전달 된 인수는 mmap 루틴이 호출되었을 때 드라이버가 캡처 한 "vma"이고 "start"및 "end"는 사용자 모드 코드에서 드라이버에 전달 된 사용자 모드 주소입니다. ioctl() 호출에 제공되는 구조체.

문제점 :

버퍼가 우리가 만든 사용자 모드에서 액세스 할 때 오래된 데이터를 것으로 보이는보고있다으로 플러시 받고있는 것으로 보이지 않는다는 것입니다 우리가 볼

. 우리의 드라이버에 대한 mmap() 호출에서 사용자 모드 주소를 얻는 대신 테스트로 mmap() API를/dev/mem에 호출합니다. 이 경우 버퍼에 대한 캐시되지 않은 액세스가 발생하므로 (플러시 필요 없음) 모든 것이 완벽하게 작동합니다.

커널 버전은 3.8.3이며 ARM 9에서 실행됩니다. 시도중인 접근 방식에 논리적 오류가 있습니까?

감사합니다.

+0

또 다른 단서는 flush_cache_range (vma, start, end)를 호출하는 대신, 나는 flush_cache_mm (vma-> vm_mm)을 호출한다. 코드가 완벽하게 작동합니다. – user1967844

답변

0

내가 대답 할 수있는 몇 가지 질문이 있습니다. 1) mmap() 전화에서 "PHYSICAL"주소는 어떻게 사용합니까? mmap는 실제 주소와 아무 관련이 없어야합니다. 2) 드라이버에서 사용자 가상 주소를 얻기 위해 정확히 무엇을합니까? 3) 어떻게 이러한 사용자 가상 주소를 실제 주소로 매핑합니까? 4) get_free_pages()를 사용하여 사전 할당 했으므로 ioremap_cache()를 사용하여 커널 공간에 매핑합니까?