Linux ‘Demand-Paging’Recall ‘mysis.c’ device-driverDeferring page-table setupsLinux ‘nopage()’ mechanismPrototype for ‘nopage()’Less to do for ‘mmap()’Demo: ‘mynopage.c’An idea for further efficiencyPage-Directory is modifiedLoop to setup directory entries‘mmtest.cpp’Is this a ‘safe’ approach?Linux ‘Demand-Paging’Using ‘nopage()’ with ‘mmap()’Recall ‘mysis.c’ device-driver•Demonstrated the ‘mmap()’ driver-method•Used ‘remap_page_range()’ function•Mapped video frame-buffer to user space•Set up all page-table entries in advance •Driver was tested using ‘mmwhere.cpp’•NOTE: A flaw was spotted by Qing Huang•A revised version now posted on websiteDeferring page-table setups•An alternative ‘mmap()’ driver-method•Don’t set up all page-tables in advance•Many entries might never be needed•Waste of cpu time to build unused entries•Our frame-buffer may span 128 MB•Each page-directory entry controls 4 MB•So there may be 32 (=128/4) page-tables!•Our screen display needs less than 8 MBLinux ‘nopage()’ mechanism•Avoids using ‘remap_page_range()’•Requires a ‘vm_operations_struct’ object•This object contains ‘callback’ functions•The main one is named ‘nopage()’•We can implement a ‘nopage()’ method•It will get called by the ‘page_fault’ handler•It can set up a needed page-table entryPrototype for ‘nopage()’struct page * my_vma_nopage(struct vm_area_struct *vma,unsigned long address,int write_access );Less to do for ‘mmap()’•In device-driver’s ‘mmap()’ method:–Does not call ‘remap_page_range()’–Installs ‘callback’ functions instead: vma->vm_ops = &my_vm_ops;Demo: ‘mynopage.c’•A working example is on course website•It can be tested using ‘mmwhere.cpp’•Changes are ‘transparent to application•But offer improved efficiency inside kernel–Less memory consumed by page-tables–Less processor time used for table setupsAn idea for further efficiency•Bypass ‘mmap()’ mechanism altogether•Use Pentium’s ‘Page-Size Extensions’•Use page-directory entries for 4MB frames•Avoids allocating/initializing page-tables•Avoids creating/inserting ‘vm_area_struct’•Mapping done by driver’s ‘open()’ method •Unmapping is done by ‘release()’ methodPage-Directory is modified•Where is task’s page-directory located? long *pgdir = current->mm->pgd;•Which directory-entries do we modify?•What page attributes should we assign?•Demo maps frame-buffer to 0x10000000•Why? It seems kernel won’t contend thisLoop to setup directory entrieslong physaddr = fb_base;long virtaddr = 0x10000000;long entry_index = (virtaddr >> 22);long entry_count = (fb_size >> 22);for (i = 0; i < entry_count; i++) {pgdir[ entry_index ] = physaddr | 0x87;physaddr += (1<<22);++entry_index;}‘mmtest.cpp’•Simple application to test ‘mymmfb.c’•It opens the device file ‘/dev/vram’•It uses ‘lseek()’ to get frame-buffer’s size•Then it directly writes to the frame-buffer•It uses the agreed-upon virtual-address:long *vram = (long)0x10000000;Is this a ‘safe’ approach?•Can we create a confliting application?•We could read the Linux source-code •Or we could perform some experiments!•Try using ‘malloc()’ to allocate regions•See if any regions overlay our frame-buffer•But how would we know if they
View Full Document