// Generate page table for IA-32e void kInitializePageTables( void ) { PML4TENTRY* pstPML4TEntry; PDPTENTRY* pstPDPTEntry; PDENTRY* pstPDEntry; DWORD dwMappingAddress; int i; // Generate PML4 Table // Except for first, set 0x00 pstPML4TEntry = ( PML4TENTRY* ) 0x100000; kSetPageEntryData( &( pstPML4TEntry[0] ), 0x00, 0x101000, PAGE_FLAGS_DEFAULT, 0 ); for ( i = 1 ; i < PAGE_MAXENTRYCOUNT ; i++ ) { // Don't use this section // Initiate 0 kSetPageEntryData( &( pstPML4TEntry[i] ), 0, 0 ,0 ,0 ); } // Generate Page Directory Pointer Table // One PDPT can handle fully 512GB // We set 64 entries for 64GB pstPDPTEntry = ( PDPTENTRY* ) 0x101000; for ( i = 0 ; i < 64 ; i++ ) { kSetPageEntryData( &( pstPDPTEntry[i]), 0, 0x102000 + ( i * PAGE_TABLESIZE ), PAGE_FLAGS_DEFAULT, 0 ); } for ( i = 64 ; i < PAGE_MAXENTRYCOUNT ; i++ ) { // Don't use this section // Initiate 0 kSetPageEntryData( &( pstPDPTEntry[i] ), 0, 0, 0, 0); } // Generate Page Directory // One page directory can handle 1GB // We set 64 entries for 64GB pstPDEntry = ( PDENTRY* ) 0x102000; dwMappingAddress = 0; for ( i = 0 ; i < PAGE_MAXENTRYCOUNT * 64 ; i++ ) { // Here is Proteced mode(32 bit) // To access 64 bit address, // access unit is MB ( >> 20 ) // For under 4GB, dwUpperBaseAddress is 0 kSetPageEntryData( &( pstPDEntry[i] ), ( i * ( PAGE_DEFAULTSIZE >> 20 ) ) >> 12, dwMappingAddress, PAGE_FLAGS_DEFAULT | PAGE_FLAGS_PS, 0 ); dwMappingAddress += PAGE_DEFAULTSIZE; } }
/** * IA-32e 모드 커널을 위한 페이지 테이블 생성 */ void kInitializePageTables( void ) { PML4TENTRY* pstPML4TEntry; PDPTENTRY* pstPDPTEntry; PDENTRY* pstPDEntry; DWORD dwMappingAddress; int i; // PML4 테이블 생성 // 첫 번째 엔트리 외에 나머지는 모두 0으로 초기화 pstPML4TEntry = ( PML4TENTRY* ) 0x100000; kSetPageEntryData( &( pstPML4TEntry[ 0 ] ), 0x00, 0x101000, PAGE_FLAGS_DEFAULT, 0 ); for( i = 1 ; i < PAGE_MAXENTRYCOUNT ; i++ ) { kSetPageEntryData( &( pstPML4TEntry[ i ] ), 0, 0, 0, 0 ); } // 페이지 디렉터리 포인터 테이블 생성 // 하나의 PDPT로 512GByte까지 매핑 가능하므로 하나로 충분함 // 64개의 엔트리를 설정하여 64GByte까지 매핑함 pstPDPTEntry = ( PDPTENTRY* ) 0x101000; for( i = 0 ; i < 64 ; i++ ) { kSetPageEntryData( &( pstPDPTEntry[ i ] ), 0, 0x102000 + ( i * PAGE_TABLESIZE ), PAGE_FLAGS_DEFAULT, 0 ); } for( i = 64 ; i < PAGE_MAXENTRYCOUNT ; i++ ) { kSetPageEntryData( &( pstPDPTEntry[ i ] ), 0, 0, 0, 0 ); } // 페이지 디렉터리 테이블 생성 // 하나의 페이지 디렉터리가 1GByte까지 매핑 가능 // 여유있게 64개의 페이지 디렉터리를 생성하여 총 64GB까지 지원 pstPDEntry = ( PDENTRY* ) 0x102000; dwMappingAddress = 0; for( i = 0 ; i < PAGE_MAXENTRYCOUNT * 64 ; i++ ) { // 32비트로는 상위 어드레스를 표현할 수 없으므로, Mbyte 단위로 계산한 다음 // 최종 결과를 다시 4Kbyte로 나누어 32비트 이상의 어드레스를 계산함 kSetPageEntryData( &( pstPDEntry[ i ] ), ( i * ( PAGE_DEFAULTSIZE >> 20 ) ) >> 12, dwMappingAddress, PAGE_FLAGS_DEFAULT | PAGE_FLAGS_PS, 0 ); dwMappingAddress += PAGE_DEFAULTSIZE; } }
/// Initialize page tables for IA-32e mode void k32PageManager::kInitPage(void) { // Allocate PML4 table kSetPageTableAddress(&pstPML4T, (PTE*)0x100000); // Set all enties as 0, except for the first entry kSetPageEntryData(&(pstPML4T[0]), 0x00, 0x101000, PAGE_FLAGS_DEFAULT, 0); for (int i = 1; i < PAGE_MAXENTRYCOUNT; i++) { kSetPageEntryData(&(pstPML4T[i]), 0, 0, 0, 0); } // Allocate PDP table kSetPageTableAddress(&pstPDPT, (PTE*)0x101000); // Set 64 entries to handle up to 64 GB // The others are set as 0 for (int i = 0; i < 64; i++) { kSetPageEntryData(&(pstPDPT[i]), 0, 0x102000 + (i * PAGE_TABLESIZE), PAGE_FLAGS_DEFAULT, 0); } for (int i = 64; i < PAGE_MAXENTRYCOUNT; i++) { kSetPageEntryData(&(pstPDPT[i]), 0, 0, 0, 0); } // Allocate PD table kSetPageTableAddress(&pstPDT, (PTE*)0x102000); int dwMappingAddress = 0; // One page table can handle 2 MB // To set 64 GB, 2 * 512 * 64 times are required for (int i = 0; i < PAGE_MAXENTRYCOUNT * 64; i++) { // Total number of bits is 64 bits // To access above 32 bits, use shift operation kSetPageEntryData(&(pstPDT[i]), (i * (PAGE_DEFAULTSIZE >> 20)) >> 12, dwMappingAddress, PAGE_FLAGS_DEFAULT | PAGE_FLAGS_PS, 0); dwMappingAddress += PAGE_DEFAULTSIZE; } return; }