/* * This file implements the Page object. A Page refers to a page of data in a * file or region of memory. The offset tracks how far into the file the page * is, and the frame tracks where in physical memory the data is located. */ #include #include #include "namespace.h" extern page_t zeroFrame; static void page_delete(Object *); /* Page object type */ ObjectType pageType = { .name = "PAGE", .size = sizeof(Page), .delete = page_delete, }; /* Destroy a Page object */ static void page_delete(Object *obj) { Page *page = (void *) obj; if (page->frame != zeroFrame) free_frame(PAGE_ADDR(page->frame)); } /* Create a new Page entry */ Page * create_page(ObjectList *cache, page_t frame, off_t offset) { Page *page = new(&pageType); page->frame = frame; page->offset = offset; add(cache, page); put(page); return page; } /* Find a Page by offset in a cache */ Page * find_page(ObjectList *cache, off_t offset) { Page *page; foreach (cache, page) { if (page->offset == offset) break; } return page; } /* Install a page into a virtual address space */ void install_page(uintptr_t addr, Page *page, int prot) { int access = PTE_PRESENT | PTE_USER; if (prot & PROT_WRITE) access |= PTE_WRITE; set_page(PAGE_ADDR(addr), page->frame | access); flush_tlb(PAGE_ADDR(addr)); } /* Get the virtual address for the mapping of a page */ void * map_page(Page *page) { /* * Since this x86 kernel doesn't keep all physical memory mapped into * the virtual address space, the page needs to be mapped into memory. * If more virtual memory was available (e.g. x86_64) all of physical * memory could be mapped to an offset, and this function would just * return (page->frame + offset); */ set_page(0x7FF000, page->frame | PTE_PRESENT | PTE_WRITE); flush_tlb(0x7FF000); return (void *) 0x7FF000; }