/** * GDT 테이블을 초기화 */ void kInitializeGDTTableAndTSS( void ) { GDTR* pstGDTR; GDTENTRY8* pstEntry; TSSSEGMENT* pstTSS; int i; // GDTR 설정 pstGDTR = ( GDTR* ) GDTR_STARTADDRESS; pstEntry = ( GDTENTRY8* ) ( GDTR_STARTADDRESS + sizeof( GDTR ) ); pstGDTR->wLimit = GDT_TABLESIZE - 1; pstGDTR->qwBaseAddress = ( QWORD ) pstEntry; // TSS 영역 설정 pstTSS = ( TSSSEGMENT* ) ( ( QWORD ) pstEntry + GDT_TABLESIZE ); // NULL, 64비트 Code/Data, TSS를 위해 총 4개의 세그먼트를 생성한다. kSetGDTEntry8( &( pstEntry[ 0 ] ), 0, 0, 0, 0, 0 ); kSetGDTEntry8( &( pstEntry[ 1 ] ), 0, 0xFFFFF, GDT_FLAGS_UPPER_CODE, GDT_FLAGS_LOWER_KERNELCODE, GDT_TYPE_CODE ); kSetGDTEntry8( &( pstEntry[ 2 ] ), 0, 0xFFFFF, GDT_FLAGS_UPPER_DATA, GDT_FLAGS_LOWER_KERNELDATA, GDT_TYPE_DATA ); kSetGDTEntry16( ( GDTENTRY16* ) &( pstEntry[ 3 ] ), ( QWORD ) pstTSS, sizeof( TSSSEGMENT ) - 1, GDT_FLAGS_UPPER_TSS, GDT_FLAGS_LOWER_TSS, GDT_TYPE_TSS ); // TSS 초기화 GDT 이하 영역을 사용함 kInitializeTSSSegment( pstTSS ); }
/// Initialize kGDT void kGDT::kInitializeGDT(void) { // Set GDTR pstGDTR = (DTR*)GDTR_STARTADDRESS; // Set GDT information pstGDTEntry8 = (GDTENTRY8*)(GDTR_STARTADDRESS + sizeof(DTR)); pstGDTR->qwBaseAddress = (QWORD)pstGDTEntry8; pstGDTR->wLimit = GDT_TABLESIZE - 1; // Segment descriptors: NULL, Code, Data, TSS kSetGDTEntry8(&(pstGDTEntry8[0]), 0, 0, 0, 0, 0); kSetGDTEntry8(&(pstGDTEntry8[1]), 0, 0xFFFFF, GDT_FLAGS_UPPER_CODE, GDT_FLAGS_LOWER_KERNELCODE, GDT_TYPE_CODE); kSetGDTEntry8(&(pstGDTEntry8[2]), 0, 0xFFFFF, GDT_FLAGS_UPPER_DATA, GDT_FLAGS_LOWER_KERNELDATA, GDT_TYPE_DATA); return; }
/** * GDT 테이블을 초기화 */ void kInitializeGDTTableAndTSS( void ) { GDTR* pstGDTR; GDTENTRY8* pstEntry; TSSSEGMENT* pstTSS; int i; // GDTR 설정 pstGDTR = ( GDTR* ) GDTR_STARTADDRESS; pstEntry = ( GDTENTRY8* ) ( GDTR_STARTADDRESS + sizeof( GDTR ) ); pstGDTR->wLimit = GDT_TABLESIZE - 1; pstGDTR->qwBaseAddress = ( QWORD ) pstEntry; // TSS 세그먼트 영역 설정, GDT 테이블의 뒤쪽에 위치 pstTSS = ( TSSSEGMENT* ) ( ( QWORD ) pstEntry + GDT_TABLESIZE ); // NULL, 커널 코드/데이터, 유저 코드/데이터, TSS를 위해 총 5 + 16개의 세그먼트를 생성 kSetGDTEntry8( &( pstEntry[ 0 ] ), 0, 0, 0, 0, 0 ); // 커널 레벨 코드/데이터 디스크립터 생성 kSetGDTEntry8( &( pstEntry[ 1 ] ), 0, 0xFFFFF, GDT_FLAGS_UPPER_CODE, GDT_FLAGS_LOWER_KERNELCODE, GDT_TYPE_CODE ); kSetGDTEntry8( &( pstEntry[ 2 ] ), 0, 0xFFFFF, GDT_FLAGS_UPPER_DATA, GDT_FLAGS_LOWER_KERNELDATA, GDT_TYPE_DATA ); // 유저 레벨 코드/데이터 디스크립터 생성 kSetGDTEntry8( &( pstEntry[ 3 ] ), 0, 0xFFFFF, GDT_FLAGS_UPPER_DATA, GDT_FLAGS_LOWER_USERDATA, GDT_TYPE_DATA ); kSetGDTEntry8( &( pstEntry[ 4 ] ), 0, 0xFFFFF, GDT_FLAGS_UPPER_CODE, GDT_FLAGS_LOWER_USERCODE, GDT_TYPE_CODE ); // 16개 코어 지원을 위해 16개의 TSS 디스크립터를 생성 for( i = 0 ; i < MAXPROCESSORCOUNT ; i++ ) { // TSS는 16바이트이므로, kSetGDTEntry16() 함수 사용 // pstEntry는 8바이트이므로 2개를 합쳐서 하나로 사용 kSetGDTEntry16( ( GDTENTRY16* ) &( pstEntry[ GDT_MAXENTRY8COUNT + ( i * 2 ) ] ), ( QWORD ) pstTSS + ( i * sizeof( TSSSEGMENT ) ), sizeof( TSSSEGMENT ) - 1, GDT_FLAGS_UPPER_TSS, GDT_FLAGS_LOWER_TSS, GDT_TYPE_TSS ); } // TSS 초기화, GDT 이하 영역을 사용함 kInitializeTSSSegment( pstTSS ); }