Q&A 게시판

리눅스 커널에 대한 Q&A 게시판 입니다. (비밀글 체크는 꼭 필요한 경우에만)

리니어 매핑과 페이지 테이블과의 관계에 대해서 질문드립니다.

작성자
이대로
작성일
2024-04-26 10:11
조회
14
안녕하세요

커널 공부하면서 올려주신 자료에서 항상 너무 도움을 많이 받고 있습니다. 감사드립니다.

리니어 매핑과 페이지 테이블과의 관계에 대해서 궁금증이 생겨 질문드립니다.

arm64에서 VMEMMAP을 사용하는 경우 모든 물리 메모리를 struct page로 관리하도록 하고 그것을 VMEMMAP_START ~ VMEMMAP_END 영역에 매핑시켜서 접근할 수 있는 것으로 이해했습니다.

http://jake.dothome.co.kr/wp-content/uploads/2016/03/fixmap-10.png
위 그림에서 표현해주셨던 리니어 매핑의 경우에는 모든 물리 메모리 공간을 가상주소(PAGE_OFFSET ~ MODULE_ADDR)에서 간단한 변환을 통해서 바로 물리 메모리 주소로 변환할 수 있는 것으로 이해했습니다.
이 영역에 대해서는 따로 가상 <-> 물리 메모리 주소를 변환해주는 테이블이 존재하지 않는 것일까요..?

개인적인 생각으로는 가상<->물리 주소가 변환이 가능하기 때문에 굳이 페이지 테이블이 필요할까? 하고 생각이 들기는 하는데..
그럼 CPU는 가상 주소만을 알고 read/write를 하는 데, 그걸 변환해주는 페이지 테이블은 있어야 되는데 하고도 생각되기도 합니다.

만약 페이지 테이블이 존재한다면 어디서 초기화 해주는지 알 수 있을까요?
전체 1
  • 2024-05-16 10:02
    이대로님 안녕하세요?

    질문이 올라와 있는지 모르고 한참 늦게 답변 드립니다 ^^;

    커널 메모리에 대해 가상 주소와 물리 메모리의 변환 성능 향상을 위해,
    가상 주소 공간이 충분히 남아도는 arm64 또는 x86등에서는 vmemmap용 가상 주소 공간을 정규 테이블에 추가 매핑하여 사용합니다.

    즉 물리 메모리를 paging_init()에서 일반 커널용 가상 주소 공간에 한 번 매핑합니다.
    그 후 sparse_init()에서 page 구조체들을 전체 메모리의 1~2%의 용량을 사용하여 생성 및 관리하는데,
    보통 기존 32비트 시스템에서는 해당 메모리 노드마다 하나의 memmap(page 구조체 덩어리)을 만들지만,
    64비트 시스템에서는 섹션단위(섹션 크기는 커널 컴파일시 결정되며 arm64의 경우 보통 1G)로 memmap을 만들고,
    추가적으로 vmemmap 공간을 활용하여 매핑하여 사용하므로써 virt_to_phys() 및 phys_to_virt() API를
    더욱 빠르게 사용할 수 있게 하였습니다.

    다음은 관련된 커널 페이지 테이블을 생성하는 코드 위치입니다.

    1. 아래 어셈블리에서 임시 테이블인 init_pg_dir을 만들어 사용합니다.
    __create_page_tables: -


    2. 그 후 아래 paging_init()에서 정규테이블인 swapper_pg_dir로 전환하여 사용합니다.
    이 때 이미 물리메모리 전부가 커널 메모리 가상 공간에 매핑하여 사용되는 상태입니다.
    그 후 sparse_init()에서 vmemmap 공간을 이용하여 추가 매핑을 합니다.
    (즉 일반 메모리는 커널 공간에 double 매핑된 상태이고, 이 메모리의 일부가 유저 메모리에서 사용하면 다시 한 번 유저 공간에 추가 매핑됩니다)

    코드 위치:
    start_kernel()
    -> setup_arch()
    -> paging_init()
    -> bootmem_init()
    -> sparse_init()

    감사합니다.

    문영일 드림.