저는 Linux가 I/O 공유 메모리를 관리하여 이를 사용하는 장치와 통신하는 방법에 대해 매우 혼란스러워합니다.
내가 올바르게 이해했다면 Linux 커널은 0x100000에서 매핑을 시작한 다음(레거시 램 데이터의 첫 번째 메가바이트를 피하고 이를 연속 메모리 위치에 저장하기 위해) 보호 모드로 들어간 후 다음과 같습니다.
- 32비트 시스템에는 다음과 같은 매핑이 있습니다.
ZONE_NORMAL은 896MB보다 작아야 하므로 커널 선형 1GB와 물리적 896MB 간의 매핑이 항상 가능합니다. 지금은 ZONE_DMA를 무시하겠습니다(이제 PCI가 메모리의 어느 곳에서나 DMA 전송을 사용할 수 있으므로 이는 이전 시스템에서만 작동한다는 것을 읽었습니다).
- 64비트 시스템에서 커널 선형 주소 공간은 PAGE_OFFSET= 0xffff810000000000에서 시작해야 합니다.
두 경우 모두 커널 공간의 주소가 PAGE_OFFSET보다 크면 ioremap 맵을 참조해야 하며(페이징을 통해 확인), PAGE_OFFSET보다 낮으면 간단한 NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET을 사용하여 확인할 수 있습니다. 맞습니까?
보너스 질문: 커널이 실행 중이고 그루밍이 완료되면 물리적으로 여전히 0x100000(첫 번째 GB 내) 주위에 상주합니까? 64비트 시스템에서도 가능합니까?
답변1
PC에서 하드웨어 메모리 매핑된 IO 범위는 BIOS에 의해 3GiB와 4GiB 사이의 물리적 메모리 주소에 할당됩니다. 드라이버가 메모리에 대한 액세스를 요청하면 커널은 이를 커널의 가상 주소 공간에 있는 위치에 매핑합니다.
그러나 다른 두 질문 중 어느 것도 공유 메모리와 관련이 없는 것 같습니다.
두 경우 모두 커널 공간의 주소가 PAGE_OFFSET보다 크면 ioremap 맵을 참조해야 하며(페이징을 통해 확인), PAGE_OFFSET보다 낮으면 간단한 NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET을 사용하여 확인할 수 있습니다. 맞습니까?
정신적으로는 그렇습니다. 두 경우 모두 하드웨어는 페이지 테이블을 사용합니다.
답변2
귀하의 질문이 다음과 같다고 생각하십시오. ioremap은 어떻게 작동합니까?
vaddr = ioremap(paddr_io_mapped_device, 크기);
vaddr은 커널 공간에서 반환된 가상 주소입니다. 커널은 가상 주소 범위( vaddr , size)에 대한 페이지 테이블 항목을 생성하고 이를 물리적 주소 paddr_io_shared_device에 매핑합니다. 따라서 가상 주소 범위에 접근하면 io_mapped 장치 내의 물리적 주소에 접근하는 것과 같습니다.
중요한 것은 반환된 vaddr은 다음과 같습니다.캐시할 수 없음. 주소 범위를 읽고 쓸 때마다 캐시가 아닌 io_mapped 장치에서 읽고 씁니다.