일단 앞절에서 살펴본 것과 같이 초기화된 인터럽트 게이트들을 가리키는 레지스터 idtr 은 startup_32 어셈블리 루틴에서 초기화된다 :
-------------------------------------- /usr/src/linux/arch/i386/kernel/head.S -------------------------------------- ENTRY(_stext) startup_32: : : #ifdef CONFIG_SMP orw %bx,%bx jz 1f /* Initial CPU cleans BSS */ pushl $0 popfl jmp checkCPUtype 1: #endif CONFIG_SMP /* SMP 가 아니면 그냥 자연스럽게 아래에 있는 : ckeckCPUtype 레이블까지 진행함 */ : checkCPUtype: : : lgdt gdt_descr lidt idt_descr : :
이때, idt_descr 이라는 심벌은 head.S 맨 아랫쪽 부분에서 다음과 같이 정의되고 있다 :
편의상 gdt_descr 까지 정의하는것까지 보였다(-_-a) 소스를 보면, idt_descr 번지에 16비트 크기(.word)로 256*8-1 의 값이 들어간다. 이부분은, 앞서 다룬 idtr 레지스터의 구조를 생각해 보면 알 수 있는 부분이다. 하위 16비트는 limit 의 의미를 띠었었다. 이것은 idtr 에 256개의 엔트리가 들어간다는 사실을 생각할 때 쉽게 알 수 있다. 그리고, 32비트 크기(.long)로 idt_table 의 주소를 저장하고 있다.
#define IDT_ENTRIES 256 #define GDT_ENTRIES (__TSS(NR_CPUS)) .globl SYMBOL_NAME(idt) .globl SYMBOL_NAME(gdt) ALIGN .word 0 idt_descr: .word IDT_ENTRIES*8-1 # idt contains 256 entries SYMBOL_NAME(idt): .long SYMBOL_NAME(idt_table) .word 0 gdt_descr: .word GDT_ENTRIES*8-1 SYMBOL_NAME(gdt): .long SYMBOL_NAME(gdt_table)
이 부분은, 위에서 이야기한 checkCPUtype 블록에서
인스트럭션에서 사용된다. lidt 명령을 인텔의 매뉴얼에서 찾아보면, 오퍼랜드가 16비트 어드레스일때와 32비트 어드레스일때의 동작이 약간 차이가 나는데(16비트 어드레스일때는 베이스에 해당하는 필드에 0x00ffffff 를 and 해서 넣음) 뭐, 제대로 만들었다고 생각하고, 어쨌든, 48비트 크기의 idtr 의 idt base address 필드(상위 32비트)에 idt_table 의 주소와, 아랫부분의 idt limit 필드(하위 16비트)에 256*8-1 개를 나타내는 값을 넣는다.
lidt idt_descr
여기까지 일단, 최초의 idt_table 의 세팅과 idtr 의 세팅을 알아보았다. 이제는 다음 섹션에서 실제 인터럽트 벡터 테이블을 세팅하는 부분을 살펴보겠다
참, idt_table 심볼이 정의되는 곳을 말하지 않았다. 그 심벌은 아래와 같이 정의되어 있다 :
-------------------------------------- /usr/src/linux/arck/i38/kernel/traps.c -------------------------------------- struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };