CS 332 w22 — Lab 5 Questions

Table of Contents

1 Miscellaneous notes

  • Note there are two vpmap.h: include/kernel/vpmap.h and arch/x86_64/include/arch/vpmap.h. The former is the one that declares vpmap_copy, and thus where you would add a declaration for vpmap_cow_copy.
  • vpmap_copy copies a page table, it is not how you would copy the contents of a page
    • Use memcpy for that
  • as_dump and as_meminfo may be helpful for debugging

2 What controls a PTE's write permission

  • arch/x86_64/include/arch/mmu.h includes a number of PTE_X macros that define masks for various parts of a page table entry
  • Each mask is 12 bits (3 hex digits)
  • The mask for write permission is #define PTE_W 0x002, which is 0000 0000 0010 in binary
  • Thus, the second bit of the PTE controls write permission
  • This is the only bit of the PTE you should change when making it read-only in vpmap_cow_copy
  • When changing the PTE back to writable in the page fault handler, you can use vpmap_set_perm to set the permissions to those of the memregion
  • For checking whether a memory region has write permission, you would use the MEMPERM macros.

3 How do we reference page tables?

  • A page table is a struct vpmap
  • The address space struct contains a pointer to the associated page table
    • The memregion struct contains a pointer to the associated address space
  • Use the vpmap_X functions to interact with the page table

4 What does a page's reference count do?

  • The kernel uses the reference count to know when an allocated page can be freed
  • Since multiple processes can share the same physical page, it can only be freed once no processes have a reference to it
  • See the pmem_dec_refcnt function:

    void
    pmem_dec_refcnt(paddr_t paddr)
    {
        struct page *page;
    
        page = paddr_to_page(paddr);
        kassert(page);
    
        spinlock_acquire(&pmem_lock);
        kassert(page->refcnt > 0);
        kassert(page->order == 0);
    
        page->refcnt--;
        if (page->refcnt == 0) {
            pmem_nfree_internal(paddr, 1, False);
        }
        spinlock_release(&pmem_lock);
    }
    

5 Are we copying a reference to the page table as well, or just the references within them?

  • In vpmap_cow_copy, like vpmap_copy, you will have two pointers—one pointing to a source PTE and the other to a destination PTE
  • The goal is to have these pointers point to identical copies
  • For example, consider this C code

    int x = 7;
    int y = 10;
    int *p = &x;
    int *q = &y;
    // how would you cause x to become a copy of y using p and q?
    // to modify what p points to, we need *p on the left side of an =
    // and we want it to have the value of what q points to, which gives us
    *p = *q;
    

6 How should we use PTE_ADDR?

  • This macro takes a page table entry and extracts the physical page number (i.e., the physical address of the start of the page)
    • It's actually identical to both ENTRY_ADDR and PPN, all defined in mmu.h
  • vpmap_copy uses it to convert the source PTE to a physical, and then virtual address for the purposes of copying over a page with memcpy
    • KMAP_P2V(PTE_ADDR(*src_pte))
  • Consider pmem_inc_refcnt—it takes a paddr_t, and PTE_ADDR is a way to go from a page table entry to a physical address