/////////////////////////////////////////////////////////////////////////////// //////////////////// Section 1: stuff to make this valid C //////////////////// #include #define NULL ((void *)0) typedef unsigned long ulong; typedef int bool; void *get_new_physical_page() { // FIX ME: this method should guarantee that the address returned is a // multiple of page_size, but this implementation does not guarantee that. return malloc(page_size); } //////////////////// Section 1: stuff to make this valid C //////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////// Section 2: parameters MMU desginers pick ////////////////// #define po_bits 12 #define pa_bits 52 #define levels 4 void *ptbr; // the page table base register - a kernel-mode register /////////////////// Section 2: parameters MMU desginers pick ////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ////////////////////// Section 3: physical address stuff ////////////////////// // a page contains 2**po_bits bytes of data #define page_size (1<>po_bits) & ((1L<> po_bits; void *page = ptbr; for(int i=0; i> ((3-i)*one_vpn_bits))&(pte_per_pt-1); // get next level of VPN PTE pte = ((PT *)page)->entries[vpn]; if (!pte.allocated) return NULL; // page fault page = pa_from_ppn(pte.ppn); // next level of tree } return page + po; } /** * If the given virtual address is already allocated, does nothing. * Otherwise, allocates the page containing that virtual address * and all intermediate page tables. */ void allocate(ulong va) { // the page offset does not impact allocation ulong vpns = va >> po_bits; void *page = ptbr; for(int i=0; i> ((3-i)*one_vpn_bits))&(pte_per_pt-1); // get next level of VPN PTE pte = ((PT *)page)->entries[vpn]; if (!pte.allocated) { // allocate a new page void *new_page = get_new_physical_page(); // ensure all its entries are marked "unallocated" for(int j=0; jentries[j].allocated = 0; // update the page table entry pte.ppn = ppn_from_pa(new_page); pte.allocated = 1; ((PT *)page)->entries[vpn] = pte; } page = pa_from_ppn(pte.ppn); // next level of tree } } //////////////// Section 5: address translation and allocation //////////////// /////////////////////////////////////////////////////////////////////////////// void main(void) { levels = 4; ptbr = calloc(page_size, 0); printf("Page fault: %p\n", pa_from_va(123456)); allocate(123456); printf("Page hit: %p\n", pa_from_va(123456)); *(int *)pa_from_va(123456) = 0x3330; printf("Value in memory: %x\n", *(int *)pa_from_va(123456)); printf("Different part of page: %p\n", pa_from_va(123450)); printf("Different page: %p\n", pa_from_va(120000)); }