Tutorial 7
Some slides are borrowed from CSCC69 offered in winter 2012
• Allowing a program to be designed as though there is only one kind of memory, "virtual" memory, which behaves like directly addressable read/write memory
(RAM).
– Need to manage what is in memory (TLB, page table, coremap)
– Swap pages on request
• When a page is requested but not in memory? Page fault
• When there is no more space in main memory to bring in pages?
– Replace, evict
• OS/161 paging uses virtual memory objects
• struct vm_object defined in src/kern/include/vmprivate.h
– A VM object defines a region of an address space
– Contains a base virtual address and an array of pages
– Redzone - A possible guard band against other vm_objects
}; struct vm_object { struct lpage_array *vmo_lpages; vaddr_t vmo_base; size_t vmo_lower_redzone;
• Each VM object has an array of logical pages (lpages), one for each virtual page in the region
• lpage stores where the page is in physical memory (lp_paddr), and where the page is stored in swap when not in main memory
(lp_swapaddr)
– If the page is not in RAM, lp_paddr is INVALID_PADDR.
– If no swap has been allocated, lp_swapaddr is INVALID_SWAPADDR.
• Low bits of lp_addr used to hold flags (DIRTY, PINNED)
• Read comments in src/kern/include/vmprivate.h
struct lpage { volatile paddr_t lp_paddr; off_t lp_swapaddr; struct spinlock lp_spinlock;
};
• lpage_create - creates an lpage object.
• lpage_destroy - deallocates an lpage, releases any RAM or swap pages involved
• lpage_lock/unlock - for exclusive access to an lpage
• lpage_copy - clones an lpage, including the contents
• lpage_zerofill - materializes an lpage and zerofill it
• Logical pages are nice, but we ultimately need to work with physical memory
• Need to keep track of physical pages
• Coremap contains an entry per page frame to indicate its status
• Inverted page table: Maps pages in memory to their virtual addresses
– It allows you to use the physical address to find the logical page that inhabits it (NULL if empty)
– Has bit flags that indicate if pages are kernel pages, pinned (busy), etc.
struct coremap_entry { struct lpage *cm_lpage;
/* logical page we hold, or NULL */
... /*flags*/
};
• tlb_replace
• tlb_invalidate(i): If you know the slot
• tlb_unmap(vaddr)
• mipstlb_getslot: None available? Call tlb_replace
• coremap_alloc_one_page(lp, pin): called when a page is needed. None free? Call do_page_replace
• coremap_{pin, unpin}: pin/unpin a page
• page_replace: returns number of the page to be evicted
– Replacement algorithm
• do_evict: performs the page eviction
• do_page_replace: starting point for page replacements
• Each lpage entry is a logical piece of memory
– That memory may be in memory
– It may also be in swap (on disk)
– Each lpage points to the location of its data
• The coremap maps physical memory usage
– When you need physical memory, consult the coremap to see what memory is free
– Each entry points to an lpage
• TLB keeps track of mapping from virtual to physical pages
• High-order word
– Virtual page number for lookup (TLBHI_VPAGE) : 20 bits (mask 0xffff000)
– Also has 6 bits for hardware PID; 6 bits unused in OS/161
• Low-order word
– Physical page number (TLBLO_PPAGE) : 20 bits
– Also has 4 status bits, and 8 unused bits
– Eg: V for “valid”, D for “dirty” (“writable”/”referenced”)
• src/kern/arch/mips/include/tlb.h
• VPN (abbr. for Virtual Page Frame Number) is the high 20 bits of a virtual address.
• PPN is the high 20 bits of a physical address space.
• When Dirty bit is 1, it means this page is writable, otherwise, it’s read-only.
• When Valid bit is 1, it means this TLB entry contains a valid translation.
• In OS161, we can just ignore the ASID part and
Global bit
• In our case the TLB is software-managed (by the
OS)
• On memory read/write, checks the entries in the
TLB in parallel:
– Entry is found - TLB hit
– Entry not found - TLB miss
• Causes EX_TLBL for loads (reads)
• Causes EX_TLBS for stores (writes)
– Protection fault - trying to write to read-only memory causes EX_MOD (modify)
• vm_fault is called from mips_trap in trap.c for any TLB exception
– Different types of VM_FAULT_* are passed on
• Eventually gets to lpage_fault (this is where you come in)
• On a TLB miss:
– Look up the page in the page table
• Implemented in src/kern/vm/addrspace: as_fault
– Choose an entry in the TLB to replace it
• In src/kern/arch/mips/mips/coremap.c: tlb_replace
– Update TLB entry with PTE from page table
• In src/kern/arch/mips/mips/coremap.c: mmu_map
• The functions that access TLB can be found at
/kern/arch/mips/include/tlb.h.
• tlb_probe: to query the TLB bank.
• tlb_read/tlb_write: to read/write a specific
TLB entry.
• tlb_random: to let the hardware decide which entry to write to.
• Minor fault: TLB does not contain a requested PTE (but it is in memory)
– Find the Page Table Entry for it and insert the new mapping into the TLB and the coremap
– See coremap.c for a function you can use! (mmu_map)
• Major fault: the desired page is not in main memory
(it’s either in swap space, or hasn’t been created yet)
– How do we know if it’s a major fault?
– lp_paddr field of the lpage struct will tell you
– lp_paddr is INVALID_PADDR if the page is not in memory
• For VM_FAULT_READ or VM_FAULT_WRITE, check address space page table if that page actually exists (PTE_P bit).
• If not, allocate a new page and modify the page table entry to insert the mapping.
– A newly allocated page should be readable and writable. If related attributes are already set, then leave them alone.
• Use tlb_random to insert this mapping to TLB.
– You can implement some other algorithm.
• Find the functions in tlb.h
• VM_FAULT_READONLY pages are already in memory and the mapping is already in TLB bank, the dirty bit is 0 and user try to write this page.
• First check if user can really write this page
– by the access bits in the low 12 bits of page table entry.
– In as_define_region, user have passed in some attributes like readable, writable and executable. Store them there and use them to check here.
– Check access right violation. Panic or kill current process, if it happens.
• If user can actually write this page, then first query TLB to get the index of the TLB entry, set the dirty bit and write it back using tlb_write().
• Change the physical page state to PAGE_STATE_DIRTY.
• Major fault: desired page is not in memory
– Page hasn’t been created yet
• A new page is allocated to the process and initialized (zerofilled) in src/kern/vm/addrspace.c: as_fault
– Page is in swap
• We need to swap the page into memory from swap space
• Need a page of physical memory for the page
– look at lpage_copy for ideas
• Set lp_*addr to INVALID_* when appropriate - to indicate page is not in main memory or swap
• Implement paging by writing the following functions:
– lpage_fault --- handles a page fault
– lpage_evict --- evicts an lpage from physical memory
– page_replace --- implements page replacement policy
• sequential replacement
• random replacement
• Much of the system is already provided
• lpage_evict – evicts an lpage from physical memory
• Really, evict the contents of the page at lp_paddr by writing it to lp_swapaddr on the swap device (if it is dirty), and marklp_paddr invalid
• Called by do_evict when a physical page is chosen for eviction
• Updating the victim’s PTE to show that it is in swap
– swap functions src/kern/vm/swap.c
• Copying it to disk (iff it is dirty)
• Evicting (/invalidating) victim’s PTE from the TLB
• Loading the new page into memory
• Updating the new page’s PTE and inserting it into the TLB
• You do not need to implement functions to move a page from disk to memory and from memory to disk (see kern/vm/swap.c).
• base-design.txt: read it
• starter code: read it
• Write test programs?
– Access lots of memory to test your paging
• Take notes
• OS161 assumes that lpages, vm_objects and address spaces are not shared.
– But one thread may access an lpage belonging to another thread, in order to evict a page
– Thus you need not use locks when accessing address spaces and vm_objects, but lpages do need synchronization
• Bit lock is used to save space (see lpage_lock/lpage_unlock)
• global_paging_lock, limits number of pages pinned at any one time
• swaplock: used by swap_alloc, swap_free, swap_reserve, swap_unreserve
• cm_pinned locks pages that are in transit.
• one bit lock per lpage
• Lock Ordering (i.e you should acquire in this order):
– global_paging_lock BEFORE coremap pages
BEFORElpages