Example #1
0
/**
 * Fills a page of memory with repeating data, used to fill empty tables in
 *
 * @param page the page number to fill in
 * @param data the address of data to fill with
 * @param data_size the size of each copt of data stored
 */
void fill_page_with_data(unsigned int page, void * data, unsigned int data_size) {
    void * phys;
    struct mmu_L1_4k_desc * L1_table;
    struct mmu_L2_4k_desc * L2_table;
    unsigned int L1_index;
    unsigned int L2_index;
    unsigned int i;
    unsigned int j;
    unsigned int entries;

    //get physical address of the page
    phys = page_number_to_address(page);

    //set up a temporary manual mapping into kernel memory
    L1_index = get_L1_index((void*)MMU_TEMP_MAP);
    L2_index = get_L2_index((void*)MMU_TEMP_MAP);

    //get the L1 table and set the entry to map to the L2 base address
    L1_table = (struct mmu_L1_4k_desc *)get_page_table_addr();
    fill_L1_index(L1_table, L1_index, MMU_L1_COURSE_TYPE, 0, 0, (void*)MMU_TEMP_L2_ADDR);
    
    //get the L2 table and set the entry to map to the physical base address
    L2_table = (struct mmu_L2_4k_desc *)(L1_table[L1_index].L2_base_addr << 10);
    fill_L2_index(L2_table, L2_index, MMU_L2_SMALL_TYPE, 0, 0, MMU_AP_USER_NONE, phys);

    //write the data out to the page
    entries = PAGE_SIZE / data_size;
    for(i = 0; i < entries; ++i)
        for(j = 0; j < data_size; ++j)
            ((char *)MMU_TEMP_MAP)[data_size*i+j] = ((char *)data)[j];

    //remove the manual mapping from the mmu (done here!)
    L2_table[L2_index].type = MMU_L2_NOMAP_TYPE; //set L2 entry to nomap
    L1_table[L1_index].type = MMU_L1_NOMAP_TYPE; //set L1 entry to nomap
}
// This clears a page table entry by clearing its present bit.
// It is called by the OS (in kernel.c) when a page is evicted
// from a page frame.
void pt_clear_page_table_entry(VPAGE_NUMBER vpage)
{
  int L1_index = get_L1_index(vpage);
  int L2_index = get_L2_index(vpage);

  PT_ENTRY* table_L2 = first_level_page_table[L1_index];
  if(table_L2 == NULL) {
    /* Control should never reach here */
    SAY("Tried to remove a vpage that does not exist!\n");
    return;
  }
  table_L2[L2_index] = 0; //clear the entry
}
// This inserts into the page table an entry mapping of the 
// the specified virtual page to the specified page frame.
// It might require the creation of a second-level page table
// to hold the entry, if it doesn't already exist.
void pt_update_pagetable(VPAGE_NUMBER vpage, PAGEFRAME_NUMBER pframe)
{
  int L1_index = get_L1_index(vpage);
  int L2_index = get_L2_index(vpage);

  PT_ENTRY* table_L2 = first_level_page_table[L1_index];
  if(table_L2 == NULL) {
    table_L2 = create_L2_page_table(L1_index);
  }

  unsigned int value = pframe | PRESENT_BIT_MASK;
  table_L2[L2_index] = value;
}
//This is called when there is a TLB_miss.
// Using the page table, this looks up the page frame 
// corresponding to the specified virtual page.
// If the desired page is not present, the variable page_fault
// should be set to TRUE (otherwise FALSE).
PAGEFRAME_NUMBER pt_get_pageframe(VPAGE_NUMBER vpage)
{

  int L1_index = get_L1_index(vpage);
  int L2_index = get_L2_index(vpage);

  PAGEFRAME_NUMBER pf_number = find_pf_number(L1_index,L2_index);

  if (pf_number == -1) { //could not be found
    page_fault = TRUE;
  }
  else{
    page_fault = FALSE;
    return pf_number;
  }
}
Example #5
0
/**
 * Gets the L2 description for a virtual memory address
 *
 * @param addr the virtual memory address to look up
 *
 * @return L2 description for the given address
 */
struct mmu_L2_4k_desc * get_L2_desc(void * addr) {
    struct mmu_L2_4k_desc * table;
    struct mmu_L1_4k_desc * entry;

    //get the L1 entry
    entry = get_L1_desc(addr);

    //if the L1 entry is no mapping, return SYSERR
    if(entry->type == MMU_L1_NOMAP_TYPE)
        return (void *)SYSERR;

    //get the page table address
    table = (struct mmu_L2_4k_desc *)((void *)(entry->L2_base_addr << 10));

    //return the single L2 description
    return &(table[get_L2_index(addr)]);
}