Linux에는 (다른 세그먼트 중에서) 사용자 데이터 세그먼트와 커널 데이터 세그먼트가 있습니다.
CPU가 사용자 모드에 있을 때 Linux는 사용자 데이터 세그먼트에 대한 세그먼트 선택기를 DS 레지스터에 로드합니다. CPU가 커널 모드에 있을 때 Linux는 커널 데이터 세그먼트의 세그먼트 선택기를 DS 레지스터에 로드합니다.
그러나 사용자 데이터 세그먼트와 커널 데이터 세그먼트가 동일한 가상 메모리 주소를 가리키기 때문에 커널 데이터 세그먼트는 여전히 사용자 모드에서 액세스할 수 있습니다.
그렇다면 Linux에는 왜 두 개의 데이터 세그먼트가 있는데, 하나는 사용자 모드용이고 다른 하나는 커널 모드용입니까?
답변1
Linux는 SS(스택 세그먼트)와 DS(데이터 세그먼트)에 동일한 세그먼트 설명자를 사용합니다. SS 세그먼트 설명자는 CPL(즉, 현재 권한 수준)과 정확히 동일한 DPL 필드를 가져야 합니다. 따라서 커널 모드와 사용자 모드에는 별도의 데이터 세그먼트 설명자가 필요합니다.
출처 (CPU 매뉴얼을 다운로드하기에는 너무 게으르다)
정의에 대한 설명gdt_페이지:
또한 긴 모드의 데이터 및 코드에 유효한 커널 세그먼트가 필요합니다. IRET는 세그먼트 유형을 확인합니다. ——카일 2000/10/28
웹 검색: iret 세그먼트 유형 확인
SS에 선택기를 로드하는 명령은 쓰기 가능한 데이터 세그먼트의 데이터 세그먼트 설명자를 참조해야 합니다. 설명자 권한(DPL) 및 RPL이 필요합니다.동일한CPL. 다른 모든 설명자 유형 또는 권한 수준 위반은 예외 13을 발생시킵니다.
웹 검색: iret 세그먼트 유형 확인 OR "DPL" OR "CPL" "SS"
...스택 세그먼트를 제외하고 레지스터 ss, CPL, RPL 및 DPL은 일치해야 합니다.정확히.
/* stack segment DPL must equal the RPL of the return CS selector,
* else #GP(SS selector) */
if (ss_descriptor.dpl != cs_selector.rpl) {
BX_ERROR(("iret: SS.dpl != CS selector RPL"));
exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc);
}
배경: Linux에는 왜 별도의암호사용자 모드와 커널 모드 세그먼트?
관련, 또 다른 댓글커널 소스 코드:
DPL이 다르기 때문에 사용자 모드와 커널 모드에서는 심지어 Long Plane 모드에서도 동일한 코드 세그먼트 설명자를 사용할 수 없습니다.
이 때문입니다현재 코드 세그먼트의 DPL이 CPL로 사용됩니다..
32비트와 64비트 코드에는 서로 다른 스니펫이 필요하다는 것을 알았습니다.
https://en.wikipedia.org/wiki/Segment_descriptor-
L=긴 패턴 세그먼트
설정된 경우 이는 64비트 세그먼트이고(D는 0이어야 함) 이 세그먼트의 코드는 64비트 명령어를 사용하여 인코딩됩니다.
적어도 x86-32의 사용자 공간에서 커널에 들어갈 때 DS 세그먼트 레지스터가 재설정되는 것 같습니다. 하지만 이 작업을 수행하는 코드를 식별할 수 없습니다.
아직 하나 있어요최근 LWN.net 기사, 이는 set_fs()에 대한 흥미로운 설명입니다.
set_fs()의 원래 기능은 x86 프로세서의 FS 세그먼트 레지스터를 설정하는 것입니다. 이는 초기에 권한이 없는 코드가 액세스할 수 있는 가상 주소 범위를 제어하는 데 사용되었습니다. 커널은 이런 방식으로 x86 세그먼트를 사용하는 것을 중단한 지 오래되었습니다.