2012-03-02 4 views
1

사용자 프로그램이동시 DMA 사용자 메모리

스레드 1을 고려

buf = malloc(9000); 
memset(buf, 0xee, 9000); 
read(buf, 9000); //for example gives pages [part of 7, 8, 9, part of 10] 

스레드 2 사용자 프로그램 :

buf = malloc(9000); //for example gives pages [part of 4, 6, 5, part of 7] 
memset(buf, 0xee, 9000); 
read(buf, 9000); 

드라이버 읽어

get_user_pages(); 

//build dma sg list from pages 
//... 

//the platform demands a cachesync 
for(all pages) { 
    dma_cache_wback_inv(); 
} 

//start dma and wait for it to be done 
//... 
wait_event_interruptible_timeout(); //blocks calling thread until dma done 

for(all pages) { 
    if(read) SetPageDirty(); 
    page_cache_release(); 
} 

페이지 7은 두 가지 모두에서 사용된다는 점에 유의하십시오. 전송, 그리고 때로는 큰 문제가 나쁜 데이터 (0xee는 한 buf의 끝에 발견)입니다. 그냥 두 개의 읽기가 서로 다른 DMA 채널에서 실행되므로 동시에 실행할 수 있습니다.

내 해결책은 사용자 드라이버에서 페이지를 정렬하여 2 개의 드라이버 DMA가 같은 페이지의 부분을 절대 공유하지 않도록하는 것이 었습니다.

다른 해결책이 있습니까? 나는 이것이 왜 큰 문제 인지도 궁금합니다.

+1

이것은 플랫폼에 따라 달라질 수 있습니다. 캐시를 무효화해야한다는 요구 사항은 임베디드 시스템에서 실행 중임을 나타냅니다. 두 개의 버퍼가 캐시 라인을 공유 할만큼 충분히 가까웠습니까? 아니면 플랫폼 정오표에 다른 제한 사항이 있습니까? –

+0

예, ppc440ep이며 버퍼가 충분히 근접합니다. 캐시 라인은 32 바이트이며, 4-12 바이트가 깨 졌거나 변경되지 않은 것으로 나타났습니다. 캐시에 동일한 실제 메모리의 두 가지 버전이 존재할 수 있습니까? 그리고 한 스레드에서 wback을 할 때, 다른 스레드의 데이터를 파괴 할 수 있습니까? 내가 아는 한 고려하지 않은 erratas는 없습니다. 그러나 get_user_pages는 어떻습니까? 동일한 페이지의 2 가지 다른 버전을 반환하면 어떻게됩니까? 다른 thread로부터의 get_user_pages 및 page_cache_release가 인터리브되는 경우. – Ronnie

+0

페이지에 실제 주소를주는 것 외에는 get_user_pages/page_cache_release가하는 일을 완전히 명확히 알 수는 없습니다. 이 시스템에는 디스크 캐시가 없으며 메모리 및 CPU 캐시 만 있습니다. – Ronnie

답변

1

이것은 임베디드 프로세서의 한계이며 캐시 일관성이없는 DMA입니다. 하이 엔드 PowerPC 칩에서이 문제는 사라집니다.

두 개의 버퍼가 만나는 지점에서 캐시 라인을 공유합니다. 한 스레드가 드라이버에 캐시를 RAM에 쓰는 것과 동시에 두 번째 스레드는 여전히 캐시 라인을 0xee로 채운 memset에 있습니다.

DMA 1은 데이터를 RAM에 기록하지만 프로세서는 여전히 해당 데이터에 대해 0xee를 포함하는 더티 캐시 라인을 보유합니다. 두 번째 스레드가 캐시를 쓰면 DMA1에서 나온 데이터에 0xee를 넣습니다.

솔루션은 다음과 같습니다

  1. 당신의 버퍼 (최고 성능) 캐시 맞 춥니 다.
  2. 커널 드라이버에서 바운스 버퍼를 사용합니다 (기존 사용자 공간 코드와 대부분 호환 됨).

get_user_pages()은 여기에서 문제가되지 않습니다. 하드웨어 및 타이밍에 관한 부분입니다.

+0

당신이 캐시 문제를 beeing에 대한 권리라고 생각하지만, memset을 사용하지 않고서도이 문제를 디버깅하기 전에 오류가 발생했다고 생각합니다. 그러나 DMA 1이 완료된 후 버퍼를 읽는 것은 가능합니다. 캐시는 DMA 2가 완료되기 전에 캐시로 0xee를 다시 읽는다. – Ronnie

+0

'malloc'은 힙 유지 보수를 위해 버퍼의 끝 부분에있는 데이터를 처리합니다. 충분할 수도 있습니다. –

+0

예, 설명과 비슷합니다. – Ronnie

관련 문제