이번 글에서는 지난시간에 알아본 세그먼테이션 과정이 윈도우에서 실제로 어떻게 진행되는지 알아보자. 프로그램이 사용하는 논리 주소가 선형 주소로 어떻게 변경되는지를 확인함으로써 윈도우에서 세그먼테이션 과정이 어떻게 진행 되는지 확인 할 수 있다. 지난번 포스트에 관해서는 아래 링크를 참조하자.

Memory Management : Segmentation 1 

Memory Management : Segmentation 2






우선 시작하기 전에, 유저 레벨에서, 그리고 커널 레벨에서 세그먼트 레지스터가 어떻게 보이는지 확인 해 보자.

[Windows 구조와 원리, 281p ~ 289p 참고] 





1. User Level


아래 스크린샷은 윈도우 Xp Sp3 - 32 Bit 에서 메모장 프로그램을 WinDBG 에 연결해서 본 레지스터 상황이다.



코드 세그먼트 셀렉터 값 : 0x1b 

데이터 세그먼트 셀렉터 값 : 0x23

이제 WinDBG에서 현재 메모장 프로그램이 사용하고 있는 셀렉터들을 dg 명령어를 이용해 확인 해 보자.



어? 0x1B 값과, 0x23 값을 가진 셀렉터는 없다. 왜 그럴까? 이유는 WinDBG 에서 dg 명령어를 통해서 보여지는 셀렉터 값들은 DPL(Descriptor Privilege Level)Bit가 모두 0인 값을 기준으로 하기 때문이다.

아래 그림을 보자. 0x1B 값에서 DPL 비트를 모두 0으로 하면 0x18값이 나오고 0x23값에서 DPL비트를 0으로 하면 0x20 값이 나온다. 빨간색으로 표시 한 부분이 레지스터 창에 보이는 값이고, 파란색으로 표시한 부분이 DPL 비트가 0이 되어 dg 명령어를 사용했을때 보이는 값이다. 0x38의 경우에는 이미 DPL 비트가 0이기 때문에 dg 명령어를 이용해도 0x38로 보인다.


FS 가 사용하는 셀렉터의 Base Address 와 Table Limit 에 대해서는 나중에 알아보기로 하고, 0x23과 0x1B가 가지는 Table Limit에 주목 해 보자. 

우리가 이미 알고 있듯이, 프로그램에서 사용할 수 있는 가상 메모리는 0x00000000 - 0xFFFFFFFF 까지다. 이중에서 0x7FFFFFFF 까지의 2GB는 유저 레벨로 사용되고 (Ring 3), 0x80000000 - 0xFFFFFFFF 까지의 2GB 는 커널레벨로 사용된다 (Ring 0)

그런데 WinDBG에서 셀렉터들을 확인하면 DPL 값이 0인 셀렉터건(Ring 0), 3인 셀렉터건(Ring 3) 모두 Base Address 가 0x00000000 이고Table Limit 이 0xFFFFFFFF 까지다.

Ring 3 사용하는 DS 셀렉터를 이용해서도 커널 메모리에 접근할 수 있다는 뜻인가? 물론 아니다. 실제로 어플리케이션에서 포인터를 이용해 커널 메모리에 접근하려 하면 메모리 접근 에러가 난다.

이는, 윈도우가 세그먼테이션을 이용해서 메모리 접근 보호를 하고 있지 않기 때문이다. 윈도우에서는 페이징을 통해서 어플리케이션에서 커널 메모리로 접근하는 것을 제한 하고 있다.




이제 FS 에 대한 의문을 풀어보자. 왜 FS 는 Base Address 가 0x7ffdc000 이며 Table Limit 이 0xFFF ( 즉, 세그먼트당 0x1000 = 4KB ) 인걸까?

FS 는 32Bit 프로세서인 80386 부터 제공되었으며 프로그램에서 보조적인 용도로 사용할 수 있도록 CS, DS, ES, SS 외에 추가적으로 제공 해 준 레지스터다. 윈도우즈에서는 FS 레지스터를 TEB(Thread Environment Block) 을 지정하는데 사용하고 있다.
TEB 는 유저 모드에서 사용하는 스레드 정보 저장 구조체다.

( TEB 에 대해서 알고 싶다면 다음을 링크를 참고하라. PEB, TEB, EPROCESS, KPROCESS, ETHREAD, KTHREAD )

그렇다면, FS 가 TEB 를 가리키므로 현재 0x7ffdc000에 TEB 가 있다는 말이 된다. 한번 확인 해 보자.


종합해보면 다음과 같다.

"User Level에서 FS는 현재 프로그램이 사용하고 있는 스레드의 정보를 저장하고 

있는 TEB 를 가리킨다." 



그렇다면 스레드가 여러개 일때 TEB 도 여러개가 되어야 하는데, 다른 TEB 는 어느곳에 저장되는 것일까? WinDBG를 통해 확인 해 보자. WinDBG 는 현재 메모장 프로그램에 붙어있다.



메모장 프로그램의 Process ID = 514 이며, 스레드는 현재 2개를 사용하고 있다. 

하나는 Thread ID = 0x848 = 2120d, TEB at 0x7ffdd000

다른 하나는 Thread ID = 0x258 = 600d, TEB at 0x7ffdc000 (현재 Thread)

아래는 ProcExp 를 통해 확인 해 본 Thread Creation Time 이다.




재밌는 점은 

0x848 = 2120d 번 스레드가 먼저 생성 되었음에도 TEB 가 존재하는 주소 번지가 (0x7ffdd000)

0x258 = 600d 번 스레드 보다도 하위에 있다는 점이다. (0x7ffdc000)

더 늦게 생성 된 스레드의 TEB 가 더 하위 메모리에 존재 한다는 의미다. 이는 아마도 윈도우즈 운영체제에서 스레드의 개수를 최대 2048개 만큼 제한 해 놓았기 때문일 것이다.

스레드는 기본적으로 1MB의 스택을 사용하므로 가상 메모리상에서 스레드는 최대 2048개(2GB)가 될 수 있다. 스레드가 2048개라면, TEB도 2048개 여야 하고 따라서 0x1000 (TEB SIZE) x 0x800 (NUMBER OF THREAD) = 0x800000 만큼의 메모리를 차지하는데 최초의 TEB는 0x7ffdd000 에서 시작하므로 나중에 생성된 TEB 가 더 상위 메모리에 존재한다면 마지막 2048번째 TEB는 0x807dd000 에 존재하게 된다. 그러나 이 곳은 커널 영역이므로 TEB 가 존재할 수 없다. (TEB는 유저 레벨에서 사용되는 구조체다. 커널레벨에서는 ETHREAD 구조체가 사용된다.) 이런 이유에서 더 나중에 생긴 TEB 가 더 하위 메모리에 존재 한다. (복군의 추측.^^)


이처럼 각각의 스레드가 같은 FS (0x38) 를 사용하면서 세그먼트의 Base Address( = TEB의 주소) 를 다르게 한다는 의미는 스레드 스위칭이 발생할 때마다 Wiondows 에서 그 내용을 바꾸어 주고 있다는 것을 뜻한다.







2. Kernel Level


이번엔 커널 레벨에서 사용하는 셀렉터에 대해서 알아보자.



유저 레벨과 다른점은 

1. CS 가 0x8 셀렉터를 사용한다는 점.
2. DS가 유저 레벨과 같이 0x23 셀렉터를 사용 한다는 점.
2. SS가 유저 레벨에선 DS와 같은 0x23 셀렉터를 사용했지만 커널 레벨에서는 0x10 셀렉터를 사용한다는 점.
3. FS가 0x38 셀렉터가 아니라 0x30 셀렉터를 사용한다는 점.

이렇게 3가지이다.

아래는 dg 명령어를 이용해 커널에서 사용하는 셀렉터를 나열한 것이다.


궁금한 점을 하나씩 풀어보자. CS의 경우는 딱히 의문점이 없다. Ring 0이므로 당연히 DPL 값이 0인 세그먼트 셀렉터를 사용해야 한다.

2. DS가 유저 레벨과 같이 0x23 셀렉터를 사용 한다는 점.

왜 유저 레벨과 똑같이 DPL이 3인 세그먼트 셀렉터를 커널 레벨에서 사용할까? 이유는 다음과 같다. 



" 낮은 권한의 코드 세그먼트로부터 높은 권한의 코드 세그먼트로의 실행 전환은 

해당 세그먼트가 Conforming 이거나 Gate를 통해서 가능하다. 그러나 

Conforming 세그먼트이건 Non - Conforming 세그먼트이건 높은 권한을 가진 

코드 세그먼트에서 낮은 권한을 가진 세그먼트로의 실행 전환은 불가능하다. 



데이터 세그먼트의 경우에는 Non - Conforming이다. 즉, 낮은 권한을 가진 

프로그램이나 프로시저는 높은 권한을 가진 데이터 세그먼트로의 접근이 

불가능하다. 그러나 반대로, 높은 권한을 가지고 있는 프로그램이나 

프로시저로부터 낮은 권한의 데이터 세그먼트로의 접근은 가능하다. "



이렇게 인텔 프로세서에서 커널의 DPL (Descriptor Privilege Level) 값이 0인 코드 세그먼트로부터 DPL (Descriptor Privilege Level) 값이 3인 데이터 세그먼트로의 접근이 가능하기 때문에 커널을 위한 DPL (Descriptor Privilege Level) 값이 0인 데이터 세그먼트 셀렉터를 사용하지 않는 것이다.




3. SS가 유저 레벨에선 DS와 같은 0x23 셀렉터를 사용했지만 커널 레벨에서는

0x10 셀렉터를 사용한다는 점.
 



스택 세그먼트도 데이터 세그먼트의 일종이다. 하지만 SS 레지스터를 사용해 세그먼트를 선택하는 스택의 경우에는 DS 를 사용하는 경우와는 조금 다르다. 아래의 인텔 문서에 다음과 같이 나와 있다.

"프로세서는 SS 레지스터로 스택 세그먼트 셀렉터를 로드할때 권한을 검사한다. 

로드할 스택 세그먼트와 관련된 모든 권한들이 CPL (Current Privilege Level)과 

매치 되어야 한다. 즉, 현재 가지고 있는 권한인 CPL 과 로드할 세그먼트 셀렉터의 

RPL (Requested Privilege Level)과 해당 세그먼트를 설명하는 GDT 내의 디스크

립터가 가지고 있는 DPL (Descriptor Privilege Level)이 모두 같아야 한다. 만약, 

RPL과 DPL이 CPL와 같지 않다면, #GP가 발생한다."




4. FS가 0x38 셀렉터가 아니라 0x30 셀렉터를 사용한다는 점.


User Level (Ring 0) 에서는 FS가 0x38 셀렉터를 사용하며 TEB (Thread Environment Block) 를 가리킨다. 하지만, Kernel Level (Ring 3) 에서는 FS가 0x30 셀렉터를 사용하여 KPCR (Kernel's Processor Control Region) 를 가리킨다. 

이 말은 프로그래머가 인터럽트를 핸들링 함으로써 유저 레벨로부터 커널 레벨로 제어 이행이 수행될 경우 반드시 FS 레지스터를 커널 레벨의 세그먼트 값 0x30으로 바꿔 주어야 한다는 뜻이다. 만약 그렇게 하지 않을 경우, 커널 레벨에서 실행되는 함수들은 KPCR 혹은 KPRCB를 참조 하는 것이 아니라TEB를 참조하는 엉뚱한 상황이 발생 할 것이다.

KPCR 은 커널에서 프로세서의 정보를 관리하기 위해서 사용하는 구조체다. 따라서 프로세서가 만약 2개라면 2개 존재하고, 1개라면 1개 존재한다. WinDBG 에서 확인 해 보자. !pcr (Processor Control Region) 명령어를 이용해 확인할 수 있다.


IDT, GDT, Thread, IRQL 등에 관한 정보를 담고 있다. 아래는 KPCR 의 구조체를 WinDBG 를 통해 확인한 내용이다.

마지막 0x120에서 볼 수 있는 구조체가 중요한데, 이름이 KPRCB (Kernel's Processor Contorl Block) 이다. WinDBG를 이용해서 어떤 정보들을 담고 있는지 확인 해 보자.




KPRCB 는 우리가 흔히 커널이라 부르는 NtosKrnl.exe 에 의해서 사용되는 비 공개 구조체다. 이름에서 볼 수 있듯이 프로세서를 제어하기 위해 사용하는 구조체다. WinDBG를 통해서 확인 해 보자.


FS:[0]이 KPCR을 가리키므로, KPCR 내의 0x120에 위치하는 KPRCB 은 fs:[120]이다. KPRCB 는 Native API에 의해서 주로 쓰이는데 대표적인 예가 PsGetCurrentThread 와 IoGetCurrentProcess 다. 한번 확인 해 보자. 아래는 PsGetCurrentThread 를 어셈블리어 형태로 변환한 결과다.

FS:[124] 값을 eax로 로드 해 리턴한다. FS:[124]는 KTHREAD 구조체다.


이번엔 IoGetCurrentProcess 를 분석해 보자.

FS:[124]를 통해서 KTHREAD 를 EAX 로 옮기고, KTHREAD + 0x44 로부터 값을 얻어와 EAX로 옮기고 리턴한다.

KTHREAD 0x44는 뭘까?, WinDBG 에서 확인해보면  0x34는 _KAPC_STATE고, 여기서 0x10을 더하면 _KPROCESS가 된다.

결국 IoGetCurrentProcess는 _KPROCESS 를 리턴한다.

EPROCESS 의 첫번째 인자가 KPROCESS 이므로 결국 IoGetCurrentProcess 는 KPROCESS 또는 EPROCESS 구조체를 리턴한다고 말할 수 있다.

ETHREAD의 경우도 마찬가지다. ETHREAD 의 첫번째 인자가 KTHREAD 이므로 PsGetCurrentThread 는 KTHREAD 또는 ETHREAD를 리턴한다고 말할 수 있다.





여기까지 유저 레벨과 커널 레벨에서 사용하는 세그먼트 셀렉터에 대해서 알아보았다. 다음 시간에는 논리 주소를 선형 주소로 변환 해 봄으로써 윈도우에서 세그먼테이션이 어떻게 일어나는지 확인 해 보겠다.

Posted by cyj4369
,

이번시간의 목표는 프로그램에서 사용하는 논리 주소 (Logical Address) 를 선형 주소 (Linear Address) 로 변경 함으로써 세그먼테이션 과정이 어떻게 일어나는지 확인 하는 것이다. 세그먼테이션에 대해서는 지난번 글을 확인 하도록 하자.

Memory Management : Segmentation 1

Memory Management : Segmentation 2

Memory Management : Translating Logical Address to Linear Address 1

인텔 X86 아키텍처에서 논리 주소가 물리 주소로 변경되는 과정은 다음과 같이 요약할 수 있다.


논리주소
 -> 세그먼테이션 -> 선형주소 -> 페이징 -> 물리주소


자, 이제부터 시작 해 보자. 어느 논리 주소를 선형 주소로 변경 할 것인가? 

이전 포스트에서 언급했던 PsGetCurrentThread 함수가 위치한 논리 주소를 선형 주소로 변경 해 보자. WinDBG 에서 확인해보면 PsGetCurrentThread 함수는 0x8052993c 에 위치한다.

kd> x nt!PsGetCurrentThread

8052993c nt!PsGetCurrentThread = <no type information>

kd> u 8052993c
nt!PsGetCurrentThread:
8052993c 64a124010000    mov     eax,dword ptr fs:[00000124h]
80529942 c3              ret

kd> db 8052993c
8052993c  64 a1 24 01 00 00 c3 cc-cc cc cc cc 64 a1 24 01  d.$.........d.$.
8052994c  00 00 8b 80 68 01 00 00-c3 cc cc cc cc cc 64 a1  ....h.........d.



첫 한바이트의 값은 0x64 다. 이 함수에 접근하기 위해서 커널에서 사용하는 셀렉터는 0x08 이다.

 
이것을 셀렉터 포맷에 맞추어 분석 해 보면

kd> .formats 0x08
Evaluate e-pression:  
Hex:     00000008  
Decimal: 8  
Octal:   00000000010  
Binary:  00000000 00000000 00000000 00001000  
Chars:   ....  
Time:    Thu Jan 01 09:00:08 1970  
Float:   low 1.12104e-044 high 0  
Double:  3.95253e-323
TI 


Flag = 0, RPL = 0 이고, GDT 에서 1번째 ( GDT의 디스크립터는 0번째부터 시작한다. ) 디스크립터를 사용한다는걸 알 수 있다.WinDBG를 통해서 GDT의 위치를 확인 해 보자.

kd> r gdtrgdtr=8003f000

GDT
 를 8바이트 (디스크립터)의 사이즈 만큼씩 잘라서 내용을 보면 아래와 같다.


kd> dq 8003f000
8003f000  00000000`00000000 00cf9b00`0000ffff
8003f010  00cf9300`0000ffff 00cffb00`0000ffff
8003f020  00cff300`0000ffff 80008b04`200020ab
8003f030  ffc093df`f0000001 0040f300`00000fff
8003f040  0000f200`0400ffff 00000000`00000000
8003f050  80008954`c0000068 80008954`c0680068
8003f060  00009302`2f40ffff 0000920b`80003fff
8003f070  ff0092ff`700003ff 80009a40`0000ffff



첫번째는 00000000`00000000 으로 채워진 널 디스크립터고, 두번째가 바로 CS가 사용하고 있는 인덱스가 1인 세그먼트 디스크립터다커널에서 사용하는 GDT 디스크립터 구조체 타입으로 변경해서 확인 해 보자.


kd> dt _KGDTENTRY -r 8003f008
nt!_KGDTENTRY
   +0x000 LimitLow         : 0xffff
   +0x002 BaseLow          : 0
   +0x004 HighWord         : __unnamed
      +0x000 Bytes            : __unnamed
         +0x000 BaseMid          : 0 ''
         +0x001 Flags1           : 0x9b ''
         +0x002 Flags2           : 0xcf ''
         +0x003 BaseHi           : 0 ''
      +0x000 Bits             : __unnamed
         +0x000 BaseMid          : 0y00000000 (0)
         +0x000 Type             : 0y11011 (0x1b)
         +0x000 Dpl              : 0y00
         +0x000 Pres             : 0y1
         +0x000 LimitHi          : 0y1111
         +0x000 Sys              : 0y0
         +0x000 Reserved_0       : 0y0
         +0x000 Default_Big      : 0y1
         +0x000 Granularity      : 0y1
         +0x000 BaseHi           : 0y00000000 (0)



요약해보면 Base Address 는 0이고, G Flag = 1에 Limit Field 가 0xFFFFF 이므로, Table Limit 은 0xFFFFFFFF 다. CS 가 사용하고 있는 세그먼트는 0x00000000 ~ 0xFFFFFFFF 이므로 선형 주소를 구하기 위해서는 현재 논리 주소에다가 Base Address 인 0을 더하면 선형주소가 나온다. 따라서 우리가 원했던 0x8052993c 의 선형주소는 0x8052993c 이다.

윈도우즈에서 사용하는 코드와 데이터 세그먼트의 베이스 어드레스는 0x00000000 이다. 아래를 확인 해 보자. WinDBG 에서 dg 명령어를 이용해 커널에서 사용하는 세그먼트 셀렉터들을 나열해 본것이다.



kd> dg 0 255
                                  P Si Gr Pr Lo
Sel    Base     Limit     Type    l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0000 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
0008 00000000 ffffffff Code RE Ac 0 Bg Pg P  Nl 00000c9b  (커널 코드)
0010 00000000 ffffffff Data RW Ac 0 Bg Pg P  Nl 00000c93 (커널 스택 세그먼트)
0018 00000000 ffffffff Code RE Ac 3 Bg Pg P  Nl 00000cfb (유저 코드)
0020 00000000 ffffffff Data RW Ac 3 Bg Pg P  Nl 00000cf3 (유저 - 커널 데이터 , 유저 스택 세그먼트 )
0028 80042000 000020ab TSS32 Busy 0 Nb By P  Nl 0000008b
0030 ffdff000 00001fff Data RW Ac 0 Bg Pg P  Nl 00000c93
0038 00000000 00000fff Data RW Ac 3 Bg By P  Nl 000004f3
0040 00000400 0000ffff Data RW    3 Nb By P  Nl 000000f2
0048 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
0050 8054c000 00000068 TSS32 Avl  0 Nb By P  Nl 00000089
0058 8054c068 00000068 TSS32 Avl  0 Nb By P  Nl 00000089
0060 00022f40 0000ffff Data RW Ac 0 Nb By P  Nl 00000093
0068 000b8000 00003fff Data RW    0 Nb By P  Nl 00000092
0070 ffff7000 000003ff Data RW    0 Nb By P  Nl 00000092
0078 80400000 0000ffff Code RE    0 Nb By P  Nl 0000009a
0080 80400000 0000ffff Data RW    0 Nb By P  Nl 00000092
0088 00000000 00000000 Data RW    0 Nb By P  Nl 00000092
0090 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
0098 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00A0 821b23f8 00000068 TSS32 Avl  0 Nb By P  Nl 00000089
00A8 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00B0 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00B8 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00C0 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00C8 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00D0 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00D8 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000
00E0 f86fa000 0000ffff Code RE Ac 0 Nb By P  Nl 0000009f
00E8 00000000 0000ffff Data RW    0 Nb By P  Nl 00000092
00F0 804fc698 000003b7 Code EO    0 Nb By P  Nl 00000098
00F8 00000000 0000ffff Data RW    0 Nb By P  Nl 00000092
0100 f8397400 0000ffff Data RW Ac 0 Bg By P  Nl 00000493
0108 f8397400 0000ffff Data RW Ac 0 Bg By P  Nl 00000493
0110 f8397400 0000ffff Data RW Ac 0 Bg By P  Nl 00000493


윈도우즈에서 코드와 데이터 세그먼트의 베이스 어드레스가 0이므로 선형주소 = 논리 주소 공식이 성립한다.

다음시간에는 이렇게 변환한 선형주소가 어떻게 페이징되어 물리 주소로 변경되는지에 대해서 알아 보겠다.

Posted by cyj4369
,

시스템 디스크립터, System Descriptor 



세그먼트 디스크립터의 S 비트가 클리어 ( 0 ) 되어 있다면, 해당 디스크립터가 가리키는 세그먼트는 시스템 디스크립터다. 그렇다면 시스템 디스크립터는 무엇인가? Intel 문서에서는 다음과 같이 정의한다

 - LDT 세그먼트 디스크립터

 - TSS 디스크립터

 - Call - Gate 디스크립터

 - Interrupt - Gate 디스크립터

 - Trap - Gate 디스크립터

 - Task - Gate 디스크립터


이렇게 6가지다. 시스템 디스크립터에 대한 인텔의 설명은 아래와 같다.




해석하자면, " 시스템 디스크립터 타입은 두가지 종류로 나뉜다. 하나는 시스템 세그먼트를 가리키고 있는 시스템 세그먼트 디스크립터 (System Segment Descriptor)고, 다른 하나는 코드 세그먼트 내부에 존재하는 프로시저들을 가리키는 포인터들을 가지고 있거나, TSS의 세그먼트 셀렉터를 가리키고 있는 게이트 디스크립터(Gate Descriptor)로 나뉜다. "


위 표는, 타입 비트에 따른 시스템 세그먼트의 내용이 무엇을 의미하는지를 알려준다.

이제까지 우리는 논리 주소 변환 과정인 세그먼테이션에서 사용되는 디스크립터 테이블에 대해서 알아 보았다. 그렇다면 이제까지 우리가 알아 본 세그먼트 디스크립터는 어디에 존재할까?  




세그먼트 디스크립터 테이블, Segment Descriptor Table 이다.




세그먼트 디스크립터는, 세그먼트 디스크립터 테이블에 존재하며, 세그먼트 디스크립터 테이블은 GDTR, LDTR 레지스터가 각각 가리키고 있다.

간단하게 설명하자면, 각각의 내용은 테이블에 담겨 있으며, 해당 테이블은 프로세서에서 그 테이블만 가리키기 위해서 설정 해 놓은 레지스터가 가리키고 있는 것이다.

디스크립터 테이블에 대해서 알아보기 전에, 시스템에서 Memory - Management 를 위해서 사용하는 레지스터에 대해서 알아보자.






MEMORY - MANAGEMENT REGISTERs for GDT, LDT


프로세서는 4 종류의 메모리 관리용 레지스터를 제공한다. GDTR, LDTR, IDTR, TR 이 그것들 이다. 이 레지스터를 로드하고 저장하기 위해서 프로세서는 특별한 명령어를 제공한다. 이번 글에서는 GDT와 LDT를 위한 GDTR과 LDTR에 대해서만 알아본다.



GDTR, Global Descriptor Table Register



GDTR 레지스터는 Global Descriptor Table, GDT 의 32Bit의 Base Address 와 16Bit의 Table Limit을 포함하고 있다.
Base Address 는 선형 주소상의 GDT 시작 주소를 나타내며, Table Limit 은 GDT 의 한계 주소를 나타낸다.

프로세서는 GDT를 GDTR 로 Load 하고 Store 하기 위해서 각각 LGDT, SGDT 명령어를 제공한다. 프로세서가 리셋되거나 켜졌을때 GDTR의 Base Address 는 0으로, Table Limit은 0FFFFh 로 초기화되며 Protected - Mode 로 전환시 GDT 의 Base Address 와 Table Limit을 GDTR로 로드해야 한다.



LDTR, Local Descriptor Table Register


LDT는 GDT 내에 존재하는 LDT 세그먼트 디스크립터(2번 시스템 세그먼트 디스크립터)를 통해 접근할 수 있는 세그먼트다. LDT 세그먼트의 디스크립터는 반드시 GDT 내에 존재해야 한다. LDTR 레지스터는 Segment Selector, LDT의 Base Address, LDT의 Table Limit, LDT의 Segment Attributes 을 담고 있다.

Base Address는 LDT 세그먼트의 선형주소를, Table Limit은 한계 주소를 나타낸다. 

LLDT와 SLDT 명령어를 통해 LDTR에 LDT를 Load 하고, Store 할 수 있다. LLDT가 세그먼트 셀렉터를 LDTR로 로드할때 Basee Address, Table Limit, Descriptor Attributes 가 LDT 세그먼트 디스크립터로부터 자동적으로 로드된다. 

Task Switching이 발생하면 LDTR은 새로운 세그먼트 셀렉터와 디스크립터의 내용으로 자동적으로 채워진다. 하지만, 이전의 LDTR 내용은 저장되지 않는다. 컴퓨터 전원이 켜지거나, 리셋될때 LDTR의 Base Address는 0으로, Table Limit은 0FFFFh 로 초기화 된다.





그렇다면, 이들 GDTR 과 LDTR 은 어떻게 이용되는 것일까? 

다시 주제를 디스크립터 테이블, Descriptor Table 로 돌려보자.






GDTR은 GDT를 가리키는데 사용되고, LDTR은 LDT를 가리키는데 사용된다. 세그먼트 셀렉터의 TI 비트를 통해서 접근해야 할 메모리가 Global Descriptor Table ( 0 ) 에 존재하는지, Local Descriptor Table ( 1 ) 에 존재하는지를 결정한다.

각시스템은 반드시 한개의 GDT 를 정의해야 하며, 이렇게 정의된 GDT는 시스템에 존재하는 모든 프로그램과 태스크에 의해서 사용된다. 추가적으로 시스템은 한개, 혹은 그 이상의 LDT 를 정의할 수 있다. 예를들어 LDT 는 분리되어 동작하는 각 태스크마다 정의 될 수도 있고 모든 태스크들이 같은 LDT 를 공유할 수도 있다.

GDT 는 세그먼트가 아니다. (LDT 는 세그먼트다.) GDT 는 선형 주소내에 존재하는 Data Structure (For Segment Desciptor) 이며 GDT 의 Base Address 와 Table Limit 은 GDTR 에 담겨 있다. (우리는 위에서 이미 GDTR이 이러한 기능을 한다는것을 알아 보았다.) GDT의 Base Address 는 프로세서의 성능을 위해서 8 Byte 단위로 정렬 되야 한다.

하나의 디스크립터 크기는 64 비트, 즉 8 Byte 다. GDTR의 Table Limit 비트가 16 비트이므로, 8 단위로 나누면 최대 8192(2의 13승) 만큼의 디스크립터를 GDT 내에 포함할 수 있다. 세그먼트 셀렉터의 인덱스 비트가 13 비트 인 이유도 여기에 있다. GDTR이나 LDTR 의 Table Limit 비트가 16비트이므로 8 Byte 단위의 디스크립터를 모두 가리키려면 2의 13승, 8192 만큼의 비트가 필요하기 때문이다.

GDT 의 디스크립터중 첫번째 디스크립터는 "NULL Desciprotr" 라고 불리며 사용되지 않는다. 데이터 세그먼트 셀렉터(DS, ES, FS, GS)가 널 디스크립터를 가리키는 것은 예외를 발생시키지 않지만, 널 디스크립터를 통해서 메모리에 접근하려는 시도는 #GP 를 발생시킨다. 초기화 과정에서 세그먼트 셀렉터를 널 디스크립터로 지정해 두는것은 사용되지 않은 레지스터를 통해 메모리 접근하려는 시도를 막기 위함이다. 

LDT 는 LDT 타입 시스템 세그먼트에 존재하며, GDT 는 이 LDT 를 가리키는 세그먼트 디스크립터를 포함해야 한다. LDT 가 여러개라면 개수만큼의 LDT 세그먼트 디스크립터가 GDT 내부에 존재해야 하며 LDT 디스크립터는 GDT 어느곳에나 존재할 수 있다.



(위의 문단은 영어실력의 부족으로 인해 해석할 수가 없다.)









논리(가상) 주소가 선형 주소로 바뀌는 과정, SEGMENTATION



우리는 이전 글, Memory Management : Segmentation 1 과 이번 글 통해서 세그먼테이션에서 사용되는 레지스터와 각종 구조체에 대해서 알아 보았다. 세그먼테이션 과정을 전체적으로 정리해 보자.


우리가 흔히 알고 있는 세그먼트 레지스터, 정식 명칭은 세그먼트 셀렉터Segment Selector 로서 어느 세그먼트를 선택할 지를 나타낸다.

Index 는 GDT (or LDT) 의 몇번째 세그먼트 디스크립터를 선택할지를 나타내며, TI 비트를 통해서 우리가 원하는 세그먼트 디스크립터가 GDT에 존재하는지, LDT 에 존재하는지를 결정한다.


GDTR 로 구한 GDT의 베이스 어드레스로부터, 세그먼트 셀렉트의 인덱스 X 8 만큼의 주소를 더해서 원하는 세그먼트 디스크립터에 접근 해서 세그먼트의 정보를 나타내는 디스크립터를 얻는다.

그리고 세그먼트 디스크립터로부터 세그먼트의 베이스 어드레스와 기타 정보들을 얻는다. 여기서 얻은 세그먼트의 베이스 주소를 통해 세그먼트에 접근하고, 여기에 우리가 가지고 있는 주소, 즉 논리 주소를 더해 선형 주소를 얻는다.



이것이 바로 세그먼테이션이다.

윈도우에서는 이렇게 얻어진 선형주소를 페이징을 통해 다시 실제 물리 주소를 변환하며, 만약 해당 운영체제가 페이징 기능을 사용하지 않는다면 이 선형주소는 실제 물리주소가 될 수 있다.

Posted by cyj4369
,


위 그림은 X86 CPU에서 제공하는 세그먼테이션과 페이징 기능을 통해 Logical Address 를 Physical Address 로 바꾸는 과정이다.

이번시간에는 이 부분중 Segmentation 에 대해서 알아보자. 단, 이 문서에서는 세그먼테이션이 무엇인지 설명하지 않으므로 자세한 내용은 아래 문서를 참고하라. 

Intel® 64 and IA-32 Architectures Software Developer's Manual
Combined Volumes 3A and 3B: System Programming Guide, Parts 1 and 2
 




위 그림에서 왼쪽의 세그먼테이션 부분만 잘라내서 확인해 보자.

위 그림에서 볼 수 있듯이 16 Bit 의 세그먼트 셀렉터(Segment Selector)를 이용해 디스크립터 테이블(Descriptor Table)에서 원하는 세그먼트 디스크립터(Segment Descriptor)를 선택하고 여기서 베이스 주소(Base Address)를 구해 유효 주소(Effective Address)를 더함으로써 선형 주소(Linear Address)를 얻을 수 있다.





자, 그럼 세그먼트 셀렉터(Segment Selector)란 무엇인가?


세그먼트 셀렉터는, 세그먼트 레지스터(Segment Register)다. 우리가 흔히 이야기 하는 CS, DS, SS, ES, FS, GS 등이 모두 세그먼트 셀렉터다. 세그먼트 레지스터를 이용해 디스크립터 테이블에서 세그먼트 디스크립터를 선택(Select) 하기에 세그먼트 셀렉터 라고 부르는 것이다. 그리고 이렇게 선택된 디스크립터 테이블이 세그먼트를 가리키는 역할을 한다.

아래는 Intel 에서 제공하는 문서에 나와있는 세그먼트 셀렉터의 정의다.


해석하면, " 세그먼트 셀렉터가 바로 세그먼트를 가리키는 것이 아니라 세그먼트를 정의하는 세그먼트 디스크립터를 가리킨다. "

세그먼트 셀렉터의 구조는 다음과 같다.


셀렉터의 13개 Bit ( 3 - 15 ) 는 테이블을 가리키는 인덱스로 사용된다.

TI Bit 는 이 셀렉터가 가리키는 세그먼트 디스크립터가 전역 디스크립터 테이블(GDT, Global Descriptor Table)에 있는지, 지역 디스크립터 테이블(LDT, Local Descriptor Table)에 있는지를 나타낸다. 0일경우 GDT, 1일경우 LDT이다. GDT 와 LDT는 아래에서 자세히 알아본다.

RPL Bit 는 셀렉터가 가리키는 세그먼트의 권한을 나타낸다. 익히 알고 있듯이 권한 값은 0 - 3까지의 값이며 윈도우의 경우 커널 레벨은 0, 유저레벨은 3의 값을 가진다.

우리는 보통 세그먼트 레지스터를 16Bit 라고 알고 있지만, 사실세그먼트 레지스터는 보이지 않는 부분과 보이는 부분으로 나누어져 있다.

세그먼트 레지스터는 위의 그림에서 보듯 보이는 부분(Visible Part)과 보이지 않는 부분(Hidden Part)으로 나누어져 있다. 보이는 부분을 세그먼트 셀렉터 라 부르며 보이지 않는부분까지 포함해서 세그먼트 레지스터라고 부른다. 세그먼트 레지스터가 변경될때, 즉 세그먼트 셀렉터가 새롭게 로드되면 해당 셀렉터가 가리키는 세그먼트 디스크립터를 참조해서 세그먼트의 기본 주소, 최대 주소, 접근 권한을 보이지않는 부분(Hidden Part)에 로드한다.

세그먼트 셀렉터는 16 Bit 이기에 세그먼트에 대해서 자세한 정보를 포함하고 있지 않다. 단순히 어느 디스크립터 테이블을 선택할지만을 알려준다. 따라서, 세그먼트에 대해서 자세한 정보를 포함하고 있는 구조체가 필요하다.




이것이 바로 세그먼트 디스크립터(Segment Descriptor)다. 

세그먼트 디스크립터에 대한 Intel 의 정의는 아래와 같다.


해석하자면, " 세그먼트 디스크립터는 GDT와 LDT에 존재하며 세그먼트의 위치와, 접근권한, 상태등에 대한 정보를 알려주는 구조체다. "



아래는 세그먼트 디스크럽터의 구조를 나타낸 표이다.



Base Address Field  는 세그먼트의 시작 주소다.

Segment Limit Field 는 세그먼트의 한계 주소다. 그런데, Base Address 는 32 Bit 인 반면에 Limit Field 는 20 Bit이다. 그렇다면 세그먼트의 최대 크기는 1MB란 뜻인가? 물론 당연히 아니다. (Granularity) 비트가 세팅 (1) 되어 있을 경우 단위가 4KB가 되어 최대값은 4GB 가 된다. 반대로 G 비트가 클리어 (0) 되었을 경우 단위는 1Bit가 되어 최대 1MB 의 한계 값을 가진다.

Type Field 는 이 세그먼트가 어떤 종류의 세그먼트로 사용되는지를 나타낸다. 이 필드의 값을 통해서 코드 세그먼트인지, 데이터 세그먼트인지, 각각의 경우 읽고 쓰기가 가능한지등의 값을 나타낸다.

System (Descriptor Type) Flag 가 클리어 (0) 되어있을경우 해당 디스크립터가 가리키는 세그먼트는 시스템 세그먼트로 사용된다. 반대로 세팅(1) 되어 있을 경우 해당 디스크립터가 가리키는 세그먼트는 코드 또는 데이터 세그먼트로 사용된다.

DPL (Descriptor Privilege Level) Field 는 해당 디스크립터로 접근할 수 있는 메모리의 특권 레벨을 나타낸다. 

P (Segment - Present) Flag 가 세팅 (1) 되어 있을 경우 해당 세그먼트는 물리 메모리에 올라와 있어 접근 가능함을 의미하며, 클리어 (0) 되었을 경우 해당 세그먼트 디스크립터가 가리키는 메모리는 접근할 수 없다. 아래 그림은 P 비트가 클리어 되었을 경우 세그먼트 디스크립터의 내용이 어떻게 구성되는지를 나타낸다.


위는 WinDBG 에서 확인한 GDT 디스크립터의 구조체다.




L (64 Bit Code Segment ) Flag 는 IA-32e 모드에서 디스크립터가 가리키는 세그먼트가 64 Bit - Native 코드를 포함하고 있는지를 의미한다. 만약 세팅 (1) 되어 있을 경우 해당 코드 세그먼트는 64 Bit 모드에서 실행되고 있는 것이며, 이 경우 D 비트는 클리어 (0) 되어야 한다. 반대로 코드 세그먼트에서 L 비트가 클리어 (0) 되어 있을 경우 호환 모드에서 돌아간다는 의미이며, 데이터 세그먼트의 경우에는 이 값이 반드시 0 이어야 한다. 

D / B (Default Operation Size / Default Stack Pointer Size and / or Upper Bound ) Flag 비트는 해당 세그먼트 디스크립터가 가리키는 세그먼트가 실행 가능한 코드 세그먼트인지, Expand-Down 데이터 세그먼트인지, 아니면 스택 세그먼트인지냐에 따라서 의미가 달라진다. 자세한 내용은 아래를 참고하라.


G ( Granularity ) Flag 비트는 Limit Field 에 영향을 준다. 위에서 설명 했듯이, 이 비트가 Set ( 1 ) 되어 있으면 Limit Field의 단위는 4KB 가 되고, Clear ( 0 ) 되어 있으면 단위는 Byte 가 된다.


Type Filed 는 시스템(S) 비트 연관되어 해당 세그먼트의 특성을 나타내는 역할을 한다. S 비트가 Clear ( 0 ) 되어 있으면 해당 세그먼트는 시스템 세그먼트로 사용되고, Set ( 1 ) 되어 있으면 해당 세그먼트는 코드 또는 데이터 세그먼트로 사용된다. Type Field 의 최상위 비트는 해당 세그먼트가 데이터 세그먼트인지 ( 0 ) 코드 세그먼트인지 ( 1 ) 나타낸다.


아래는 WinDBG에서 확인한 GDT 디스크립터의 구조이다.


kd> dt _KGDTENTRY -r
nt!_KGDTENTRY
   +0x000 LimitLow         : Uint2B
   +0x002 BaseLow          : Uint2B
   +0x004 HighWord         : __unnamed
      +0x000 Bytes            : __unnamed
         +0x000 BaseMid          : UChar
         +0x001 Flags1           : UChar
         +0x002 Flags2           : UChar
         +0x003 BaseHi           : UChar
      +0x000 Bits             : __unnamed
         +0x000 BaseMid          : Pos 0, 8 Bits
         +0x000 Type             : Pos 8, 5 Bits
         +0x000 Dpl              : Pos 13, 2 Bits
         +0x000 Pres             : Pos 15, 1 Bit
         +0x000 LimitHi          : Pos 16, 4 Bits
         +0x000 Sys              : Pos 20, 1 Bit
         +0x000 Reserved_0       : Pos 21, 1 Bit
         +0x000 Default_Big      : Pos 22, 1 Bit
         +0x000 Granularity      : Pos 23, 1 Bit
         +0x000 BaseHi           : Pos 24, 8 Bits






데이타 세그먼트, Data Segment

해당 세그먼트가 데이터 세그먼트일때. Type Field 의 2, 1, 0 비트는 각각 AccessdWrite - EnableExpension - Direction 을 의미한다. 데이터 세그먼트는 Read - Only, Rea - Write 둘 중 하나의 속성을 가질 수 있다. 

 데이터 세그먼트의 한 종류인 스택 세그먼트 (Stack Segment)는 반드시 Read - Write 속성을 가져야 한다. 그렇지 않을 경우에는 SS 레지스터가 Non - Writable Memory 를 셀렉터로 로드할 경우 General - Protection - Exception (#GP) 를 발생시킨다.

E (Expension - Direction) Flag  클리어 ( 0 ) 되어 있을 경우에는 메모리는 상향 확장  ( Expand - Up ) 되며, 반대로 세팅 ( 1 ) 되어 있을 경우에 메모리는 하향 확장 ( Expand - Down ) 된다.

동적으로 최대 크기가 변할 필요가 있는 스택 세그먼트와 같은 경우에는 E Flag 는 세팅 ( 1 ), Expand - Down  되어야 하며, 만약 최대 크기가 고정되어 있는 스택 세그먼트라면 클리어 ( 0 ), Expand - Up 되어야 한다.

Accessed Bit 는 해당 세그먼트가 Excutive나 운영체제에 의해서 Clear 된 이후로 다시 접근되었는지를 나타낸다. 프로세서는 해당 세그먼트를 셀렉터로 로드 할 때 마다 Accessed Bit를 세팅 한다.







코드 세그먼트, Code Setment



코드 세그먼트는 Type Field 의 최상위 비트가 1이다. 이후의 비트들은 높은 순서대로 2, 1, 0, 각각 AccessedRead - EnableConforming Flag로 해석된다. 코드 세그먼트는 Read - Enable Flag에 따라서 실행 가능하거나, 실행 가능하고 읽기 가능한 세그먼트가 될 수 있다. 

Excutable / Read 세그먼트는 ROM 과 같은 곳에서 정적 변수나 상수가 코드와 같이 존재할때 사용할 수 있다. Protected Mode 에서 코드 세그먼트는Non - Writable 이다.

Accessed 비트는 데이타 세그먼트와 같기에 따로 설명하지 않고 넘어가겠다.

Conforming (대체할 한국어 단어를 찾지 못하겠다.) Flag 는 해당 세그먼트가 낮은 권한을 가진 코드 세그먼트로부터 실행이 전환될 수 있는지를 나타낸다. 만약 실행이 전환될 세그먼트가(대상) Conforming Segment 라면 더 높은 권한을 가졌더라도 Current Previlege Level 에서 실행 가능하며, 대상 세그먼트가 Non - Conforming Segment 라면 Call Gate 나 Task Gate 를 이용하지 않는 한 #GP 를 발생한다.

시스템에서 사용하는 유틸리티 중 접근이 불가능하게 설정 되어 있는 특정한 예외를 위한 핸들러(나눗셈 예외)나 장치같은 경우는  Conforming Segment 에 로드된다. 반면 낮은 권한의 프로시저나 프로그램으로 부터 완벽하게 보호되어야 하는 것들은 Non - Conforming Segment 에 로드된다.

해석하자면, " Call 이나 Jmp 를 통해서 낮은 권한의 (산술적으로 높은) 코드 세그먼트로의 접근은 대상 세그먼트가 Conforming 이건, Non - Conforming 이건 #GP 를 발생시킨다. "


모든 데이터 세그먼트는 Non - Conforming Segment 다. 즉, 낮은 권한의 프로시저나 프로그램은 자신들이 가진 데이터 세그먼트보다 높은 권한을 가진 데이터 세그먼트에 접근할 수 없다. 하지만, 코드 세그먼트와는 다르게 데이터 세그먼트는 높은 권한으로부터 낮은 권한을 가진 세그먼트로의 접근이 가능하다. 

System Descriptor 에 대해서는 2장에서 알아본다.

Posted by cyj4369
,

Linux kernel 을 보고 있는데, 책 마다 base kernel version 이 조금씩 달라서 source code 가 많이 차이가 나더군요.

Understanding Linux Kernel : 2.6.11 version

Professional Linux Kernel Architecture : 2.6.24 version

The Linux Kernel Archives 에서 kernel source code download 할 수 있는데, 2.6.11 이나 2.6.24 와 같이 아주 예전(?) version 의 경우에는 바로 보이지 않아서 
어떻게  download 하는지 몰랐었습니다.

혹시 저같은 분을 위하여 link 적어봅니다. :) 
http://www.kernel.org/pub/linux/kernel/ 에 각 버전별로 압축되서 올라와 있으므로 원하시는 버전 찾으셔서 download 하실 수 있습니다.

http://www.kernel.org/pub/linux/kernel/v2.6/

2.6.11 source (Understanding Linux Kernel base code)

2.6.24 source (Professional Linux Kernel Architecture base code)

 

http://www.kernel.org/pub/linux/kernel/ // 2.6 이전 버전도 directory 선택하여 download 가능.

'Embedded Lab > linux, x86' 카테고리의 다른 글

[Memory Management : Segmentation 2]  (0) 2012.10.08
[Memory Management : Segmentation 1]  (0) 2012.10.08
[우분투 한글 입력기 nabi 설치 및 설정]  (0) 2012.09.25
[JTAG & UART]  (0) 2012.09.13
[Flash Memory(NOR / NAND)]  (0) 2012.09.12
Posted by cyj4369
,

******************************************************************************

1. nabi를 설치한다

$sudo apt-get install nabi

2. 설치가 완료되면 nabi를 기본 입력기로 설정한다.

$sudo im-switch -c

3. nabi를 기본으로 설정한다.

$sudo im-switch -c

4번째 정도에 nabi 설정이 있다. 설정한다.

4. reboot

X윈도우를 사용하고 있다면

ctrl + alt + backspace 를 눌러서 간단히 X윈도우만 재시작이 가능하다.

******************************************************************************



언어설정 변경하기


우측 상단의 '사용자명 - System Settings'를 클릭합니다.


'Language Support'를 클릭합니다.


'Install / Remove Languages...'를 클릭합니다.

'Korean'을 체크하고 'Apply Changes'를 클릭합니다.

'한국어'가 표시되었습니다.


여기서 '한국어'가 표시되지 않는 경우가 생길 수도 있습니다.

이 경우 로그아웃-로그인 후, '한국어'를 삭제한 뒤 재설치 해봅니다.


이제 '한국어'를 드래그하여 최상단에 위치시킵니다.

그 후 'Apply System-Wide'를 클릭합니다.

'Keyboard input method system(키보드 입력 시스템)'을 'nabi'로 바꿔줍니다.


'Regional Formats'탭을 선택합니다.

마찬가지로 '한국어'로 바꾼 후 'Apply System-Wide'를 클릭합니다.


이제 로그아웃 - 로그인합니다.


'Embedded Lab > linux, x86' 카테고리의 다른 글

[Memory Management : Segmentation 1]  (0) 2012.10.08
[리눅스 커널 소스 다운로드]  (0) 2012.10.07
[JTAG & UART]  (0) 2012.09.13
[Flash Memory(NOR / NAND)]  (0) 2012.09.12
[fork에 대한 그림 설명]  (0) 2012.09.05
Posted by cyj4369
,

JTAG [Joint Test Action Group]의 약자로 임베디드 시스템 개발시 디버깅하기 위한 장비이다. 
또, JTAG은 임베디드 시스템을 개발하기 위해 통합한 회로로 사용되는 IEEE 1149.1의 일반적인 이름이지만, 
보통 디버거를 가리킨다.
하드웨어상 발생하는 인터럽트나 시그널을 발생 및 조작하며 세세한 디버깅이 가능해진다.
다른용도로는 임베디드 시스템의 ROM(NOR Flash일 경우 등), NAND Flash등의 내용을 기록하거나 읽어 낼 수 있다. 
JTAG Port와 Cable을 이용하여 JTAG장비를 타켓시스템과 호스트시스템과 연결한후, 디버깅 및 레지스터값을 실시간으로 스텝단위로 실행 및 알아낼 수 있다.

SANYO Electric Co.,Ltd.|CA6|Normal program|Pattern|1/15sec|F/3.5|0.00 EV|6.3mm|ISO-100|Off Compulsory

위 타젯보드의 위 가운데 하늘색 선이 JTAG Port이다.

SANYO Electric Co.,Ltd.|CA6|Normal program|Pattern|1/16sec|F/3.5|0.00 EV|6.3mm|ISO-100|Off Compulsory

사진에서 하얀색 사각형의 장비, JTAG Cable로 연결된 장비가 TRACE32이다.
제공되는 기능이 워낙많아 자주 사용해보지 않으면, 그냥 Memory에 Download 기능만 수행하는 애물단지로 변신한다.
몇 천만원정도의 비싼 장비인데, 그 이유는 역시 하드웨어 런타입 Debugging이 가능하기 때문이라고 한다.

UART (Universal Asynchronous Receiver/Transmitter-범용비동기화 송수신기)는 컴퓨터에 부착된 직렬장치들로 향하는 인터페이스를 제어하는 프로그램이 들어 있는 마이크로칩이다. 
UART는 컴퓨터에게 
RS-232C DTE인터페이스를 제공함으로써, 모뎀이나 기타 다른 직렬장치들과 통신하거나 데이터를 주고받을 수 있게 한다. 이 인터페이스의 일부로서, UART는 또한 다음과 같은 일을 수행한다.

Serial 케이블을 이용해 호스트시스템과 연결하며, 연결된 통신내용은 콘솔창을 통해 확인이 가능하다.
즉 타겟 시스템의 다운로드된 프로그램이 잘돌아가는지 호스트시스템에서 확인이 가능하다.
이때 호스트 시스템상에서 마우스와 키보드 인터럽트를 캐치할 수 있다. 
진보된 UART들은 일정량의 데이터 버퍼링을 제공함으로써, 컴퓨터와 직렬 장치들의 데이터 스트림이 대등하도록 맞추어준다. 즉 컴퓨터의 동작속도를 장치의 속도와 동등하게 맞추도록 요구하는 장치를 관리할 수 있다.

SONY|DCR-TRV520|Normal program|1/100sec|F/1.6|0.00 EV|Flash did not fire

위의 처음 사진에서 타겟보드의 우측 상단의 케이블이 RS232 Serial Port이다. 이 포트를 이용하여 UART 통신이 가능해진다.

Posted by cyj4369
,



컴퓨터에 사용되는 메모리에는 여러가지가 있다.
Register부터 시작해서 Cache, RAM, ROM, 하드디스크 등 외부메모리를 포함해서 다양한 것이 있다.

여기서 말하고 싶은 것은 FLASH Memory라고 하는 반도체 메모리이다.
이는 ROM(Read Only Memory)의 일종으로 전원이 공급되지 않더라도 기억된 내용이 보존되는 비휘발성으로, 전기적으로 데이터를 지우고 다시 기록할 수 있다.


점점 FLASH Memory는 발전되고 다양한 기기에서 사용되고 있는데, 이에 대해 알아보자. 
(필자가 사용한 보드에서는 NAND Flash Memory가 사용되었음.)
가장 많이 알고 있는 사용용도는 USB드라이브가 있고, 그 외에 휴대 전화나 디지털 카메라 임베디드 보드등에서 자주 사용된다.

ROM의 일종이기 때문에 ROM을 대처한 비휘발성 메모리로 사용된다. 
ROM에 대해 간단히 알아보면 비휘발성 메모리로 전원이 공급되지 않더라도 내용이 없어지지 않고 기억을 한다. 단 RAM에 비해서 엑세스 시간은 느리다. 그 종류로는 크게

Mask ROM : 제조시 공장에서 내용 기입, 대량 생산용
PROM(Programmable ROM) : 사용자에 의해 1회 프로그래밍 가능, 이후 수정 불가능
EPROM(Erasable Programmable ROM) : 메모리 속에 저장된 내용을 지우고 재사용할 수 있는 PROM자외선을 비추면 ROM 내의 내용이 삭제, 롬 라이터 같은 장비로 내용 기입이 가능하다.
EEPROM(Electrically Erasable Programmable ROM) : 정상보더 더 높은 전압을 이용하여 반복적으로 지우거나 다시 프로그램이 가능, On-Board 상태에서 자유롭게 읽고 쓰기 가능, 단 수명이 10만회 미만으로 제한, 일부 내용 수정시에는 전체내용을 지우고 다시 프로그램 해야 함.



FLASH Memory : 
1984년 도시바에서 근무중인 마스오카 후지오 박사의 발명
읽기 속도가 빠르며, 하드 디스크보다 충격에 강하다. 블록단위로 내용을 쓰고 지울 수 있다. 무엇보다 EEPROM보다 비용이 덜 들기 때문에 여러 분야에서 사용된다. (EEPROM은 바이트 레벨에서 R/W, 플래쉬 메모리가 일반 램처럼 사용하지 못하는 이유는 RAM은 블록이 아닌 바이트 단위로 주소 지정이 가능해야 하기 때문이다.)

블록 내에서 특정 단위로 읽고 쓸 수 있지만, 블록 단위로 지워야 한다. 덮어 쓸 수 없기 때문에 모든 블록을 지우기 전까지는 해당 자료를 변경할 수 없다.


또한 백만번 정도로 지우기 횟수가 제한되어 있다.
내부적으로는 NAND와 NOR가 존재한다.

NOR
- 지우기, 쓰기 시간이 긴 대신 어떤 위치에도 임의로 접근이 가능. 그러나 덮어 쓰기와 지우기는 임의 접근이 불가능하다.
- 업데이트되지 않는 프로그램 코드를 저장

NAND
- 페이지 단위로 읽기/쓰기가 가능하지만 해당 페이지를 덮어 쓰거나 지우려면 모든 블록을 지워야 한다. 
- 블록을 여러 페이지로 나누어 사용한다.
- NOR 플래쉬 메모리에 비해 지우기와 쓰기 시간이 좀더 빠르다.
- 비트당 제작비가 NOR비해 낮다.
- 내구성이 훨신 강하다.
- 순차적인 접근만을 지원하다. (그래서 대용량 저장장치로 이용된다.)

NOR상에서는 부트코드로 부팅이 가능하나, NAND상에서는 불가능하다. 그렇기 때문에 NAND Flash Memory를 사용하게 되면 NAND의 내용을 RAM상으로 복사한후 부팅이 이루어 져야 한다.
(ROM이나 NOR Flash Memory 사용시 XIP기법-Excute in Place, ROM상에서 바로 실행)

Posted by cyj4369
,

BPLRU
 

\"사용자
 연속적인 읽기와 쓰기 요구에 대해 SSD는 하드디스크와 비슷하거나 더 좋은 performance를 가지고 있지만 random writes에서는 더 안좋은 performance가 나타난다. 이런 SSD의 poor performance는 데스크탑이나 서버 시스템에 크게 영향을 미칠수 있다. BPLRU는 flash storage의 이런 random write performance를 향상시키기 위한 새로운 write buffer management sheme이다. 이는 세가지 핵심기술(Block-level LRU, Page padding, and LRU compensation)을 사용한다.
1. Block-level LRU

  Block-level LRU는 FTL에서 merge operations의 수를 최소화 하기위해 erasable block의 크기를 고려하여 LRU list를 경신한다.
사용자 삽입 이미지
  8개의 sector는 the write buffer에 있다. 그리고 각각의 블록은 4개의 sector를 포함한다. sector 15가 다시 기록될 때, 전체 블록은 LRU list의 head로 이동한다. sector 12는 최근에 access되지 않았더라도 LRU list의 앞에 있다. free space가 필요할때, 최근에 가적 적게 사용된 블록이 victim block으로 선택된다. 그리고 victim block내의 모든 sector는 순간 cache로부터 flushed 된다. block 1은 victim block로 선택되고 sectors 5와 6은 flushed 된다.
2. Page padding

  Page padding은 the buffer flushing cost를 줄이기 위해 fragmented write patterns을 sequential write patterns로 바꿔준다.
  BPLRU는 victim block에 없는 몇 개의 page를 읽는다.그리고 순차적으로 블록 범위내의 모든 sector를 기록한다. Page padding은 불필요한 reads와 writes를 하는 것처럼 보일 수 있지만 그것은 비싼 full merge를 효율적인 switch merge로 바꿀 수 있기 때문에 더 효과적이다.
사용자 삽입 이미지
  The victim block은 오직 두 개의 sectors(12 and 15)를 가지고 있다. 그리고 BPLRU는 page padding을 위해 sectors 13과 14를 읽는다. 그러면, sectors 12-16은 순차적으로 기록된다. Log-block FTL에서, log block은 the writes 할당된다. 그리고, the log block은 현재의 데이터 블록을 복구시킨다. 로그블록은 블록내의 모든 sector에 순차적으로 기록되기 때문이다. 즉, switch merge가 발생한다.
3. LRU compensation

  LRU compensation은 random writes를 더 효과적으로 하여 RAM을 사용하기 위해 the LRU list를 조절한다.
사용자 삽입 이미지
  BPLRU block 2가 전체적으로 순차적으로 기록되는 것을 인지하고, 그것을 LRU list의 끝으로 이동시킨다. 나중에 더 많은 공간이 필요해지면 그 블록은 victim block으로 선택되고 flushed 될 것이다.

'Embedded Lab > FLASH MEMORY' 카테고리의 다른 글

[FTL 기술흐름]  (0) 2013.06.28
[NAND 플래시의 종류]  (0) 2012.10.17
[SSD 개론]  (0) 2012.09.06
Posted by cyj4369
,

SSD 기술소개
  ㆍ Solid State Drive (SSD)이란 하드디스크처럼 사용할 수 있도록 된 저장장치이다. 팍스디스크는 국내 최초로 SSD 를 개발한 이력을 보유하고 있다.
  ㆍ NAND Flash SSD란 본질적으로 플래시 메모리칩의 배열로, HDD와 호환성을 가지도록 에뮬레이션을 하는 컨트롤러를 가지고 있다.
  ㆍ 팍스디스크의 핵심 기술은 자체적으로 SSD 컨트롤러를 보유하고 있으며, SSD 시스템을 개발-생산-계측 시스템을 모두 보유하고 있다. 
       특히, 단일컨트롤러로 세계 최대용량을 지원하는 핵심 기술과 클라우드 컴퓨팅용 서버등을 위한 고객사등에 적용시키고 있다.  

■ Flash Memory의 물리적 특징
  ㆍ 전원이 끊겨도 저장된 내용이 삭제되지 않는 메모리 (c.f. ROM)
  ㆍ 읽기/쓰기가 자유로운 메모리 (c.f. DRAM/SRAM)
  ㆍ SSD (Solid state Drive) : 회전운동을 하는 하드 디스크와 달리 고정된 반도체 메모리 방식으로 무소음 작동
  ㆍ 모터 회전에 따라 자기 데이터를 읽는 하드디스크보다 몇배이상 빠르게 작동
  ㆍ 작동온도 범위도 플래시 메모리는 더 저온과 고온에서 작동이 가능
■ Flash Memory의 기술적 특징
  ㆍ 데이터를 쓰기전에 반드시 지워야 한다.
  ㆍ read/write의 단위와 지우기의 단위가 다르다 - Read/Write: page (보통 2-8kB) Erase: block (128 page)
  ㆍ read, write, erase에 소요되는 시간이 서로 다르다. - Read(0.025ms)〈 Write(0.2ms)〈 Erase(1.5ms)
  ㆍ 데이터의 신뢰성이 다른 메모리에 비해 극히 좋지 않기 때문에 오류 정정기술(ECC)이 없으면 사실상 사용이 불가능하다. 
  ㆍ 따라서 메모리셀은 지우기를 할때마다 닳아서 손상되며 수명이 제한되어 있다.
■ NOR vs. NAND 구조 비교
* NOR Flash
  ㆍ Random, direct access interface
  ㆍ Random 읽기 속도가 빠르다.
  ㆍ 늦은 지우기와 쓰기이지만, 데이터 신뢰성이 높다. (ECC 불요)
  ㆍ 프로그램 저장에 주로 사용된다
* NAND Flash
  ㆍ Block단위로 I/O 접근을 한다
  ㆍ 고밀도 저장, 저렴한 가격
  ㆍ 지우기와 쓰기가 뛰어나지만, 데이터 신뢰성이 낮다. (ECC필요)
  ㆍ 주로 (연속된) 데이터 자정에 사용된다.
■ SLC vs. MLC
  ㆍ SLC 와 MLC NAND Flash 칩은 각각 하나의 비트와 두개의 비트를 메모리셀마다 가지고 있다.

  ㆍ SLC가 MLC와 비교해 신뢰성이 높아 10만회까지 읽고/쓰기가 가능하지만 단가가 비싸다.
  ㆍ MLC는 SLC에 비해 신뢰성이 떨어져 수천회까지만 읽고/쓰기가 가능하지만 단가가 저렴하여 양산제품에 많이 사용되고 있다.
  ㆍ 대용량제품에서는 MLC를 중심으로 생산되며,산업용, 방산용 제품에서는 SLC 중심으로 생산된다.
■ NAND Flash 물리적 구조
  ㆍ 읽기는 대단히 빠르지만, 쓰기는 상대적으로 느려 SSD 컨트롤러가 버퍼를 활용하는등 모아쓰기 기법을 사용하게 된다.
  ㆍ 지우는 시간이 오래 걸려, 컨트롤러가 전체 성능에 영향을 주지 않도록 한꺼번에 지우는 작업을 백그라운드로 수행하게 된다.

■ NAND Flash Memory의 논리적 구조
  ㆍ NAND Flash는 Block과 그 하부구조인 Page 단위로만 접근이 가능하며, 단 하나의 비트만을 쓰더라도 1page 전부를 사용하게 된다.

■ SSD Architecture
Controller는 일종의 SoC(system on chip)로 Host(컴퓨터)와 독립적으로 플래시메모리를 컨트롤 하여 
안정적인 드라이브 성능을 제공하게 된다. 팍스디스크는 SSD 에 필요한 모든 IP 를 자체 보유하고 있어 맞춤형으로 설계가 가능하다.
특히, SATA 6Gbps, Multi-Port 형 초고속 LPDDR Controller 를 자체 기술로 보유하고 있고, 세계 최소형 28bit BCH-ECC 기술을 사용하고 있다. . 

■ FTL(Flash Translation Layer)
  ㆍ 플래시 메모리의 동작 특성을 숨김.
  ㆍ 일반적인 파일 시스템의 인터페이스 제공
  ㆍ 플래시 메모리를 마치 디스크 드라이브처럼 보이도록 컨트롤러에 내장된 소프트웨어

FTL은 file system의 논리적 주소를 Flash memory의 실제 물리적 주소로 상호 변환시켜줄뿐 아니라, 
Flash memory특성상 쓰기동작이 지연되는 경우, 이를 숨기거나 보완하는등 핵심적인 역할을 하는 소프트웨어이다.
■ NAND Flash SSD구조

SSD에서는 Flash memory의 수명연장이나 신뢰성 제고를 위해 다양한 기술적 요소가 필요하다.

  ㆍ Garbage Collection은 마치 PC의 디스크조각 모음과 유사한 기능을 구현하며,
  ㆍ ECC는 데이터와 별도의 Spare Array 영역에 저장해 둔 코드를 활용해서 자동으로 복구하도록 도와주며,
  ㆍ Bad block관리는 HDD가 low level포맷을 통해 사용가능영역을 확정하는것과 비슷한 역할을 백그라운드로 수행하며,
  ㆍ Wear leveling은 일정영역에 계속 쓰기를 반복하면 Flash memory의 셀이 손상되므로
  ㆍ 이를 전영역에 고르게 쓰도록 하는 쓰기균등화 기능을 자동으로 수행한다.

'Embedded Lab > FLASH MEMORY' 카테고리의 다른 글

[FTL 기술흐름]  (0) 2013.06.28
[NAND 플래시의 종류]  (0) 2012.10.17
[SSD에서 FTL 관리 기법 - BPLRU]  (0) 2012.09.09
Posted by cyj4369
,