Be myself :: 2. Protected 모드로의 전환

달력

32024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

1 개요

GDT(Global Descriptor Table)란 각종 Descriptor의 테이블을 가지고 있는 것이다. 각종 세그먼트나 여러 가지 테이블들이 어떻게 구성되어 있는지 적어놓은 하나의 메모장이라 생각하여도 좋다. 필요성은 첫째, Real mode 에서 Protected 모드로 전환하기 위해 필요한 것이다. 각 세그먼트들을 나누어야 세그먼트들의 접근 유무를 확인할 수 있기 때문이다. 둘째, GDT는 IDT(Interrupt descriptor table)의 주소 값을 가지고 있어 인터럽트가 발생 하였을 때 어떤 처리를 할 것인지 결정하는 첫 번째 역할을 한다. 이 설명만으론 뭔가 부족하다. 다음 그림은 GDT가 설정되지 않았을 때 보이는 현상이다. 마우스를 표현 하였지만, 마우스가 움직이질 않는다. GDT에 IDT등록을 하지 않아서 이다.

그냥 그림이라 마우스가 움직이는지 그렇지 않은지 직접 확인은 하지 하지만, 움직이지 않는다.(믿어달라. 혹시 직접 확인해 보고 싶은 사람은 'OS구조와 원리'책을 참고하기 바란다.)

그럼, GDT가 왜 필요한지 알았으니, GDT를 만들어 어떻게 Protected모드로 전환되는지 먼저 살펴보고, 다음 글에서 인터럽트와 함께 IDT에 관한 부분을 살피겠다.

먼저 어떠한 순서로 Real Mode에서 Protected mode로 전환되는지 살펴 보겠다.

GDT 만들기 Protected Mode 레지스터 세팅 파이프라인 지우기 prefix를 사용한 점프

* real mode와 protected mode

real mode는 16비트로 동작하고, pc가 부팅할 때 처음 동작하는 cpu모드 이다. 이 영역에선 주소설정을 자유롭게 할 수 있어 악의적인 프로그래머가 커널영역의 메모리를 자유롭게 사용할 수 있어 os를 파괴하거나 등의 보안상의 문제가 발생할 수 있다.

반면 protected mode는 32비트로 동작하고, 각 세그먼트들의 속성값을 설정하여 각 세그먼트들의 접근을 보호한다.

2 protected mode로의 전환

2.1 GDT만들기

일단 GDT테이블에 등록되는 디스크립터의 생김새를 살펴 보자.

Limit 0~15bit

Base Address 0~15bit

P

DPL

S

type

Base Address 16~23bit

Base Address 24~31bit

G

D

0

AVL

Limit 16~19bit

<GDT 디스크립터>

위 그림에 대해 설명하자면, P는 페이징 기능과 관련되어 있고 일반적으로 1을 나타낸다. DPL은 보안과 관련되어 있는데 커널 레벨인지 유저레벨인지 나타낸다. 만약 셀렉터 레지스터의 RPL이 DPL보다 레벨이 높을 경우(예를 들어 유저영역에서 커널 영역으로 접근하려 할 시) 접근하지 못하도록 차단한다. S는 시스템 세그먼트인지 코드 세그먼트인지를 나타내고 type은 읽고 쓸수 있는지, 실행할 수 있는지 등을 나타낸다. G는 세그먼트 크기 단위를 나타내는데 0이면 BYTE고 1이면 4KB이다(즉, 4G사용) D비트는 이 세그먼트가 16비트인지 32비트로 작동하는지를 나타 낸다. Limit는 세그먼트 크기이고 Base Address는 세그먼트의 첫 시작 주소를 나타낸다. Base Address와 Limit가 왜 이렇게 나누어져 있는지는 예전 cpu와의 호환성 때문이다.

2.2 Protected mode 레지스터 세팅

이렇게 여러 개의 디스크립터로 만들어진 GDT를 등록해야 하는데, 이를 GDTR이라는 레지스터에 등록한다. 이 레지스터는 48비트 크기로 첫 16비트는 GDT의 크기가, 나머지 32비트엔 GDT의 시작주소가 물리주소로 들어간다.

이렇게 설정하면, 주소 지정은 어떻게 이루어 지는지 살펴보자. 세그먼트 레지스터는 16비트의 셀렉터 레지스터(CS,DS 등등..) 와 64비트 디스크립터 레지스터로 나뉘는데, 프로그래머가 사용할 수 있는 것은 셀렉터 레지스터일 뿐이다. 디스크립터 레지스터는 GDT디스크립터와 모양이 비슷하고 셀렉터 레지스터의 모양을 살펴 보자.

Index

TI

RPL

인덱스 값은 GDT에서 찾는 디스크립터가 어디에 위치하는지 찾는 값이고 RPL은 이 세그먼트가 커널영역인지 유저영역인지 확인하는 역할을 한다.

그럼 셀렉터 레지스터에 값을 넣었을 때 어떻게 동작하는지 살펴 보겠다.

그렇다면, 결과적으로 지금까지 디스크립터 레지스터에 값을 넣기 위한 일을 한 것이다. 이렇게 구한 디스크립터 레지스터의 Base Address의 값을 통해 Protected 모드에서의 주소 지정방법을 설명할 수 있다. 예를들어 [ds:0x65]라고 한다면, 0x65와 limit를 체크하여 세그먼트 크기를 넘지 않는지 확인하고 넘지 않는다면, Base Address의 값과 0x65의 값을 합하여 물리주소의 값을 구한다.

2.3 파이프라인 지우기

우선 파이프라인을 지우기 전에 CR0의 레지스터의 최하의 비트를 1로 바꾼다. 이 비트는 pe비트라고 하며 1로 바꾸면 32비트 시스템으로 동작한다.

CPU가 연산할 때, I/O bus interface에서 명령어를 가져오고, 해석하고, 실행하고, 데이터 메모리 엑세스등의 단계를 거치는데, 단계들 마다 명령어를 각각 실행시켜 빠르게 하는 것을 파이프 라이닝 이라 한다. 쉽게 말하자면, 각 단계들을 수행하는 장치들이, 하나의 명령어를 처리하고, 그 명령어의 단계가 끝날 때까지 기다리는 것이 아니라, 다음 명령어의 그 단계를 처리한다면 더 빠르게 처리할 수 있다는 것이다. 더 자세한 사항은 기회가 되면 설명하도록 하겠다. 이러한 특성 때문에 Real mode의 16비트에서 Protected mode의 32비트로 전환 시, 현재 Excute되는 명령어만 바꾸어야 할 뿐만 아니라 cpu유닛에 남아있는 다른 단계들의 값들을 지우거나, 32비트로 바꾸어 주는 과정을 거쳐야 한다. 여기서 바꾸어 주는 과정은 따로 명령어가 없기 때문에 불가능하고, 지우는 방법을 택한다.

2.4 Prefix를 사용한 점프

16비트 레지스터에서 32비트 레지스터로 바꾸기 위해 명령어에서 제일 앞에 0x66과 0x67을 붙이면 된다. 혹은 32비트에서 16비트로 변형시킬 때도 쓰인다. 0x66은 operand prefix인데, 명령어의 오퍼렌드의 값을 변형시킨다. 0x67은 address prefix인데 대상 주소값을 변형 시킨다.

'컴퓨터구조&OS > OS' 카테고리의 다른 글

5. 보호  (0) 2014.05.05
4. Task switching  (0) 2014.05.05
3. 인터럽트 처리  (0) 2014.05.05
메모리 구조  (0) 2014.05.04
1.OS의 시작  (0) 2014.05.04
Posted by flack3r
|