/******************************************************************************* * Looks up an address in the TLB. If no entry is found, attempts to access the * current page table via cpu_pagetable_lookup(). * * @param vpn The virtual page number to lookup. * @param write If the access is a write, this is 1. Otherwise, it is 0. * @return The physical frame number of the page we are accessing. */ pfn_t tlb_lookup(vpn_t vpn, int write) { pfn_t pfn; int i; int foundPosition = -1; tlbe_t *current_entry_ptr; /* * FIX ME : Step 6 */ /* * Search the TLB for the given VPN. Make sure to increment count_tlbhits if * it was a hit! */ for (i = 0; i < tlb_size && foundPosition < 0; i++) { current_entry_ptr = tlb + i; if (current_entry_ptr->valid && current_entry_ptr->vpn == vpn) { foundPosition = i; } } if (foundPosition < 0) { /*cpu_pagetable_lookup();*/ /* If it does not exist (it was not a hit), call the page table reader */ pfn = pagetable_lookup(vpn, write); /* * Replace an entry in the TLB if we missed. Pick invalid entries first, * then do a clock-sweep to find a victim. */ for (i = 0; i < tlb_size && foundPosition < 0; i++) { if (!tlb[i].valid) { foundPosition = i; } else { if (1 == tlb[i].used) { tlb[i].used = 0; } else { foundPosition = i; } } } } else { /*** if found, increase tlb hits */ count_tlbhits++; } /***** * If all the tlb entry is used, then evict the first one */ if (foundPosition < 0) { foundPosition = 0; } pfn = tlb[foundPosition].pfn; tlb[foundPosition].used = 1; tlb[foundPosition].vpn = vpn; tlb[foundPosition].dirty = write; tlb[foundPosition].valid = 1; /* * Perform TLB house keeping. This means marking the found TLB entry as * accessed and if we had a write, dirty. We also need to update the page * table in memory with the same data. * * We'll assume that this write is scheduled and the CPU doesn't actually * have to wait for it to finish (there wouldn't be much point to a TLB if * we didn't!). */ return pfn; }
/******************************************************************************* * Looks up an address in the TLB. If no entry is found, attempts to access the * current page table via cpu_pagetable_lookup(). * * @param vpn The virtual page number to lookup. * @param write If the access is a write, this is 1. Otherwise, it is 0. * @return The physical frame number of the page we are accessing. */ pfn_t tlb_lookup(vpn_t vpn, int write) { pfn_t pfn = 0; /* * FIX ME : Step 6 */ /* * Search the TLB for the given VPN. Make sure to increment count_tlbhits if * it was a hit! */ for (int i = 0; i < tlb_size; i++) { if (tlb[i].valid && tlb[i].vpn == vpn) { count_tlbhits++; tlb[i].dirty = write; tlb[i].used = 1; pfn = tlb[i].pfn; // goto hitHouseKeeping; return pfn; /* return pfn here so the rest no need to run */ } } /* If it does not exist (it was not a hit), call the page table reader */ pfn = pagetable_lookup(vpn, write); //!HOUSEKEEPING is done here. In the pagetable_lookup(), if it found a valid pte. It will updates its information //including used, dirty. //pagetable_lookup might encounter page fault, in which case the page table will be updated /* * Replace an entry in the TLB if we missed. Pick invalid entries first, * then do a clock-sweep to find a victim. */ for (int i = 0; i < tlb_size; i++) { if (!tlb[i].valid) { //if an entry in tlb is invalid, it can be one that is removed by the tlb_clearone. //Thus it is already marked as invalid in the pagetable of that victim process. No need to //update that victim process tlb[i].vpn = vpn; tlb[i].pfn = pfn; tlb[i].valid = 1; tlb[i].used = 1; tlb[i].dirty = write; //!we already did houseKeeping in pagetable_lookup() goto housekeeping; } } int i = 0; while (1) { if (!tlb[i].used) { tlb[i].vpn = vpn; tlb[i].pfn = pfn; tlb[i].valid = 1; tlb[i].used = 1; tlb[i].dirty = write; //!we already did houseKeeping in pagetable_lookup() goto housekeeping; } else { tlb[i].used = 0; i++; i = i % tlb_size; } } housekeeping: current_pagetable[vpn].used = 1; current_pagetable[vpn].dirty = write; return pfn; // //I am quite confused about this part // hitHouseKeeping: // //If you have a hit, you should not need to access the memory(current_pagetable) again, otherwise tlb is meaningless // //However, this just been used pfn should be updated so that when other process call a page-replacement // //It will have a chance to live longer (and if it has to be swap out, the os should know if it is dirty) // current_pagetable[vpn].used = 1; // current_pagetable[vpn].dirty = write; /* * Perform TLB house keeping. This means marking the found TLB entry as * accessed and if we had a write, dirty. We also need to update the page * table in memory with the same data. * * We'll assume that this write is scheduled and the CPU doesn't actually * have to wait for it to finish (there wouldn't be much point to a TLB if * we didn't!). */ // return pfn; }