Sqix

64bit 멀티코어 OS 제작하기 [2] - 1 : 운영 모드와 레지스터 본문

MINT64 OS

64bit 멀티코어 OS 제작하기 [2] - 1 : 운영 모드와 레지스터

Sqix_ow 2018. 5. 8. 01:04

이번 글에서는 운영체제의 다섯 가지 운영 모드(리얼 모드, 보호 모드, IA-32e 모드, 시스템 관리 모드, 가상 8086 모드)와 레지스터, 메모리 관리 기법에 대해서 알아봅니다.


1. 운영 모드


64bit OS가 지원하는 운영 모드는 총 5가지입니다. 여기에는 위에서 말씀드린 리얼 모드, 보호 모드, IA-32e 모드, 시스템 관리 모드, 가상 8086 모드가 있습니다.

우리가 만들 OS에서 필수적으로 지원해야 하는 모드는, 위 5개의 모드들 중 리얼 모드, 보호 모드, IA-32e 모드입니다. 


리얼 모드


리얼 모드는 프로세스가 처음 동작할 때 진입하는 모드입니다. 어떤 상태에 있는 프로세서건 상관없이 전원이 켜지거나, 혹은 리셋되는 모든 프로세서는 모두 리얼 모드로 진입하게 됩니다. 


리얼 모드는 16비트 프로세서와 동일하게 동작하고, 바이오스의 여러 기능들을 사용할 수 있습니다. 


Real Mode의 특징


* 사용 가능한 RAM이 1MB 미만입니다.

* 가상 메모리 혹은 GDT가 지원되지 않습니다.

* 보안 메커니즘이 지원되지 않습니다.

* CPU operand 길이가 16bit 이하입니다.

* 메모리 어드레싱 모드가 제한적입니다.

* 64kb 이상의 메모리에 접근하려면 세그먼트 레지스터를 이용하여 복잡한 작업을 수행해야 합니다.

* 디바이스 드라이버를 제작하지 않아도 됩니다.

* 레지스터 크기가 작기 때문에 메모리 엑세스가 빠르게 이루어집니다.

* Low Level API를 지원합니다.


보호 모드


리얼 모드에서 64비트 모드(IA-32e)로 전환하기 위해서 거쳐가야 하는 모드입니다. 각 최대 4GB의 지정 가능한 메모리를 가진 여러 가상 주소 공간을 사용할 수 있고, 현재 OS의 필수 기능이라고 할 수 있는 멀티태스킹, 보안, 세그멘테이션, 페이징 기능을 하드웨어적으로 지원합니다. Real Mode에서만 BIOS 인터럽트가 작동하기 때문에, 보호 모드에서는 대부분의 BIOS 인터럽트를 사용할 수 없게 됩니다.


IA-32e 모드


IA-32e 모드는 32비트 호환 모드와 64비트 모드로 나뉘어집니다. 우리는 64비트 모드의 OS를 개발하기 때문에, 주로 64비트 모드에 대해서 살펴보게 될 것입니다. 


※ 운영 모드 사이의 관계와 운영 모드 간 전환


자세한 전환 과정은 각각의 코드를 작성하면서 보다 자세하게 다루게 될 것이니, 여기서는 각 모드별로 전환을 할 수 있는 경우에 대해서만 다룹니다.


[가상 8086 모드]


EFLAG REG    ↑↑                ||    EFLAG REG

VM 비트를 1로  ||              ||    VM 비트를 0으로

설정                  ||              ↓↓    설정


[    보호 모드     ]

CR0 REG의                                                                                       CR0 REG의 PG 비트 1로 설정

PE 비트를 1로 설정                                                                            CR4 REG의 PAE 비트 1로 설정

     IA32_EFER MSR REG의 LME 비트를 1로 설정


↗↙                                                            ↖↘   


CR0 REG의                                IA32_EFER MSR 레지스터의

PE 비트를 0으로 설정                  LME 비트를 0으로 설정

RESET

[ 전원 ]             ->                 [  리얼 모드  ]                            < R E S E T - - - -                                                      [IA-32e 모드]

====================================================================================================================


   ↑↑                ||   

   SMI 인터럽트 발생 ||              ||  인터럽트 핸들링 완료

   ||              ↓↓    


     [시스템 관리 모드]


2. 운영 모드와 레지스터


● 범용 레지스터


범용 레지스터는 32비트, 64비트에 모두 있으며, 기본적으로 8개의 레지스터를 공통적인 용도로 가지고 있고, 64비트(IA-32e) 모드에서는 추가적으로 R8~R15의 레지스터를 가지고 있습니다. 32비트에서는 앞에 E를, 64비트에서는 앞에 R을 붙여 구분하고, 16비트에서는 아무런 접두사가 붙지 않습니다.


기본적으로 가지고 있는 레지스터들에 대해 알아봅시다.


AX : 산술 연산을 수행할 때 누산기로 이용.

BX : 데이터의 주소를 저장할 때 포인터로 이용.

CX : 루프 혹은 문자열의 카운터로 이용.

DX : I/O의 주소를 지정할 때 사용되며, 산술 연산 수행 시 보조 레지스터로 이용.

SI : 문자열에 관련된 작업을 수행하게 될 경우, Source String의 Index로 이용.

DI : 문자열에 관련된 작업을 수행하게 될 경우, Destination String의 Index로 이용.

SP : 스택 포인터(Stack Pointer)

BP : 스택에서 데이터에 접근할 때, 데이터의 베이스 포인터로 이용(Base Pointer).


위 레지스터들의 접두사로 E를 붙이게 되면 보호 모드, R을 붙이게 되면 IA-32e 모드에서 이용됩니다.


또한, IA-32e 모드에서 추가된 R8~R15 레지스터는 필요 상황에 따라 다양하게 이용할 수 있습니다.


레지스터가 각 운영 모드와 관련이 있다고 하지만, 그렇다고 해서 모든 운영 모드에 따라 레지스터가 별개로 존재하는 것은 아닙니다. 이렇게 된다면 운영 모드의 개수 * 모든 레지스터의 개수만큼 레지스터가 있어야 하는데, 이는 비효율적입니다. 


그래서 범용 레지스터는 가장 큰 사이즈의 레지스터를 기준으로 이를 공유해서 사용합니다. 가령 IA-32e 레지스터 중 RAX가 있다고 하면 여기에서 EAX로 사용되는 경우 RAX의 절반 사이즈를 EAX로 사용하게 됩니다.


한가지 특이사항이 더 있는데, IA-32e모드의 기본 오퍼랜드 크기는 32비트, 기본 어드레스 크기는 64비트로 설계되어 있습니다. 따라서 RIP의 기본 어드레스는 64비트 주소를 표현할 수 없기 때문에 새로운 표현 방식이 필요하게 되었습니다. 그것이 바로 RIP 상대 주소라는 새로운 방식입니다.


기본 오퍼랜드 사이즈만을 이용한다면, 32비트이기 때문에 위,아래로 2GB 단위밖에 표현할 수 없습니다. 따라서 프로세서 제조사에서는 jmp 명령어에 예외를 두어서 분기 명령 시에는 오퍼랜드 사이즈를 64비트로 하여 전체 어드레스 범위에서 이동할 수 있도록 하였습니다.


● 세그먼트 레지스터


세그먼트 레지스터는 주소 영역을 다양하게 구분하는 역할을 합니다. 크기는 16비트로, CS, DS, SS, ES, FS, GS 총 6개로 구성됩니다. 운영 모드마다 세그먼트 레지스터의 역할은 조금씩 차이가 있는데, 리얼 모드(16bit)에서는 고정 크기의 주소 영역을 지정하는 역할만 하고, 보호 모드(32bit)와 IA-32e(64bit)에서는 접근 권한, 세그먼트의 시작 어드레스와 크기를 지정하는데 사용됩니다. 이를 통해 커널 영역을 보호하는 기능을 구현할 수 있습니다.


각 세그먼트의 역할은 다음과 같습니다.

- CS : 코드 영역을 가리키는 레지스터로, jmp나 int 관련 명령으로만 변경이 가능합니다.

- DS : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있으며 데이터 영역에 접근할 때 임시로 사용됩니다.

- ES : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있으며 문자열과 관련된 작업을 처리할 때 임시로 사용됩니다.

- FS : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있습니다.

- GS : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있습니다.

- SS : 스택 영역을 가리키는 레지스러로, 데이터 이동 명령으로 값을 변경할 수 있으며 SP, BP 레지스터를 통해 스택 접근을 할 시 임시로 사용됩니다.


● 컨트롤 레지스터


컨트롤 레지스터는 운영 모드를 바꾸고 기능을 제어하는 레지스터입니다. x86에서는 CR0 ~ CR4까지 5개의 레지스터가, x86_64에서는 CR5가 추가되어 총 6개의 컨트롤 레지스터가 존재합니다.


각 레지스터의 역할은 다음과 같습니다.

-CR0 : 운영모드를 제어하는 레지스터로, 리얼모드 <-> 보호 모드 간 전환하는 역할과 캐시, 페이징 기능 등을 활성화시킵니다.

-CR1 : 프로세서에 의해 예약되는 레지스터

-CR2 : 페이지 폴트 발생 시 발생한 선형(논리) 주소가 저장되는 레지스터

-CR3 : 페이지 디렉토리의 물리 주소와 캐시에 관련된 기능을 설정하는 레지스터

-CR4 : 프로세스에서 지원하는 확장 기능을 제어하는 레지스터로, 페이지 크기를 늘리거나 메모리 영역을 확장시키는데 사용됩니다.

-CR8 : Task 우선순위에 있는 레지스터의 값을 제어하는 레지스터로, 외부 인터럽트를 걸러주는 역할을 합니다. IA-32e 모드에서만 접근이 가능합니다.


각 레지스터들의 구조는 다음과 같습니다.


(출처 : http://egloos.zum.com/miooim/v/48142)


다음 글에서는 메모리 관리 기법에 대해서 알아보겠습니다.


Comments