Linux ‘Demand-Paging’ Using ‘nopage()’ with ‘mmap()’

Download Report

Transcript Linux ‘Demand-Paging’ Using ‘nopage()’ with ‘mmap()’

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 website
Deferring 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 MB
Linux ‘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 entry
Prototype 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 setups
An 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()’ method
Page-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 this
Loop to setup directory entries
long
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 did?