bool LongModePaging::allocate_page_table(triple_list high_level_entry) { bool succeed =true; for( triple_list_ptr it=high_level_entry.begin() ; it!=high_level_entry.end() ; it++) { if( !allocate_page_table((*it).first , (*it).second,(*it).third)) succeed = false; } return succeed; }
/*****-----functional interface of LongMode-Paging----*****/ bool LongModePaging::map_page_table(Address addr , void* pg_ptr , bool pbuffer) { //std::cout<<"map:"<<std::hex<<addr<<std::endl; unsigned pml4,pdp,pd,pt; get_domains(addr , pml4 , pdp , pd , pt , mode); unsigned buffer_entry_id = get_buffer_table_off(addr,buffer_table_shift,mode); assert( (pml4!=(unsigned)(-1)) && (pdp!=(unsigned)(-1))); PageTable* table; if( mode == LongMode_Normal) { assert( (pd!=(unsigned)(-1)) &&(pt!=(unsigned)(-1))); table = allocate_page_table(pml4,pdp,pd); if( !table ) { debug_printf("allocate page table for LongMode_Normal failed!"); return false; } if( pbuffer) { //std::cout<<"extend one buffer map"<<std::endl; extend_one_buffer_map(addr,table,pg_ptr , pt, buffer_entry_id, buffer_table_entry_num); } else { validate_entry(table , pt , pg_ptr); } } else if( mode == LongMode_Middle ) { table = allocate_page_directory( pml4 , pdp); if(!table) { debug_printf("allocate page directory for LongMode_Middle failed!"); return false; } if( pbuffer ) extend_one_buffer_map(addr , table , pg_ptr , pd , buffer_entry_id , buffer_table_entry_num); else validate_entry( table,pd, pg_ptr); } else if( mode == LongMode_Huge ) { table = allocate_page_directory_pointer(pml4); if(!table) { debug_printf("allocate page directory pointer for LongMode_Huge failed!"); return false; } if(pbuffer) extend_one_buffer_map(addr , table ,pg_ptr, pdp,buffer_entry_id , buffer_table_entry_num); else validate_entry(table,pdp,pg_ptr); } return true; }
/* *@function: allocate page table according to input *%attention: information of current page tables must can be contained within page directory entries before or when allocating page table *@param pdt_entry: list of (page directory pointer entry id , page direcotry entry id) */ bool PAEPaging::allocate_page_table(pair_list pdt_entry) { bool succeed = true; for( pair_list_ptr it= pdt_entry.begin(); it!=pdt_entry.end();it++) { if( !(allocate_page_table((*it).first , (*it).second)) ) { succeed= false; debug_printf("allocate page directory for entry %d for page directory pointer failed"); } } return succeed; }
bool LongModePaging::allocate_page_table(Address addr , Address size) { bool succeed = true; assert(mode==LongMode_Normal); if( addr & 0x1fffff) { fatal("must align with 2MB"); succeed = false; } unsigned pml4_entry = get_pml4_off(addr , mode); unsigned pdp_entry = get_page_directory_pointer_off(addr , mode); unsigned pd_entry = get_page_directory_off(addr , mode); unsigned page_table_num = (size+0x1fffff)>>21; for( unsigned i =0 ;i<page_table_num ; i++) { if( allocate_page_table(pml4_entry , pdp_entry , pd_entry+i)==false) succeed = false; } return succeed; }
bool PAEPaging::allocate_page_table(Address addr , Address size) { bool succeed = true; if ( addr & 0x1fffff ) { fatal("base address must align with 1MB"); return false; } unsigned pd_offset = get_page_directory_off( addr , PAE_Normal); unsigned pdp_offset = get_page_directory_pointer_off( addr , PAE_Normal); unsigned page_num = (size+0x1fffff) >>21; assert( page_num + pd_offset < 512); for( unsigned i=0 ; i<page_num ; i++) { if (allocate_page_table( pdp_offset ,i+pd_offset)==false) { debug_printf("allocate %d page table for 0x%x failed",page_num , addr); succeed = false; } } return succeed; }
/*****-----functional interface of paging----*****/ bool PAEPaging::map_page_table(Address addr, void* pg_ptr , bool pbuffer) { unsigned pdp_id = get_page_directory_pointer_off( addr , mode); unsigned pd_id = get_page_directory_off(addr,mode); unsigned buffer_entry_id = get_buffer_table_off(addr,buffer_table_shift,mode); PageTable* table; if( mode == PAE_Normal) { unsigned pt_id = get_pagetable_off(addr , mode); if( (table = allocate_page_table(pdp_id , pd_id))==NULL ) { debug_printf("allocate page table failed"); return false; } if( pbuffer ) { extend_one_buffer_map(addr , table , pg_ptr , pt_id , buffer_entry_id , buffer_table_entry_num); } else { validate_entry(table , pt_id ,pg_ptr); } } else if( mode == PAE_Huge) { if( (table=allocate_pdt(pdp_id))==NULL) { debug_printf("allocate page directory failed !"); return false; } if( pbuffer) extend_one_buffer_map(addr,table, pg_ptr , pd_id, buffer_entry_id , buffer_table_entry_num); else validate_entry( table , pd_id , pg_ptr); } return true; }
/********************** ************************/ int main(int argc,char *argv[]) { int n_pages = 0; //int n_frames = 0; ram_info_t ram_info;// ram_info.n_frames = 0;// ram_info.algorithm = NULL;// int n_cache = 0; int n_tlb = 0; char *access_file = NULL; FILE *access_fd = NULL; addr_t virtual_addr = 0; addr_t physical_addr; pid_t pid = 0; char mode; /* * Parse arguments */ if( 0 != parse_args(argc, argv, &access_file, &n_pages, &ram_info.n_frames, &n_cache, &n_tlb, &ram_info.algorithm) ) {// return -1; } /* * Setup data structures */ srand(time(NULL)); current_ref = (char *)malloc(sizeof(char) * MAX_LINE); clear_stats(); stats.cache_size = n_cache; stats.tlb_size = n_tlb; stats.num_pages = n_pages; stats.num_frames = ram_info.n_frames;// printf("Allocating resources...\n"); allocate_cache(n_cache); allocate_tlb(n_tlb); allocate_page_table(n_pages); allocate_page_directory(n_pages); //allocate_ram(n_frames); allocate_ram(ram_info); /* * Open the file that we are going to read */ if( NULL == (access_fd = fopen(access_file, "r") ) ) { fprintf(stderr, "Error: Unable to open the access file <%s>\n", access_file); return -1; } /* * Read page requests from the file */ gettimeofday(&stats.start, NULL); while(0 == feof(access_fd) ) { /* Read one line */ current_ref[0] = '\0'; if( NULL == fgets(current_ref, MAX_LINE, access_fd) ) { break; } /* Strip off the newline */ if( '\n' == current_ref[strlen(current_ref)-1] ) { current_ref[strlen(current_ref)-1] = '\0'; } extract_args(current_ref, &pid, &mode, &virtual_addr); /* * Memory management operations to access the page */ if(VERBOSE){ printf("-----------------------------------------------------------\n"); printf("%s: Process %*d \t Access [Page %4d, Offset %#05x] (%#010x)\n", current_ref, MAX_PID_LEN, pid, GET_PAGE(virtual_addr), GET_OFFSET(virtual_addr), virtual_addr); } access_page(pid, mode, virtual_addr, &physical_addr); if(VERBOSE){ printf("%s: Process %*d \t Access [Page %4d, Offset %#05x] (%#010x) --> (%#010x) [Frame %4d, Offset %#05x]\n", current_ref, MAX_PID_LEN, pid, GET_PAGE(virtual_addr), GET_OFFSET(virtual_addr), virtual_addr, physical_addr, GET_FRAME(physical_addr), GET_OFFSET(physical_addr)); } } gettimeofday(&stats.end, NULL); display_stats(); /* * Cleanup */ fclose(access_fd); if( NULL != current_ref ) { free(current_ref); current_ref = NULL; } free_ram(); free_page_dir(); free_tlb(); free_cache(); return 0; }