For Kernel_Newbies By a Kernel_Newbie
page_present is not set.(pte_present) do_swap_page looks up a swap_cache and
gets in a page.It removes the page from the swap cache (swap_free),and does a
set_pte. A page contains some hints regarding its location in the swap. A swap
cache entry contains 6 bits to indicate Swap Type, (64 swap devices
supported),and 24 bits are retained for SWAP_OFFSET within the swap device.
Given a swap entry,you can lookup a swap cache by doing lookup_swap_cache, and
get the page.If its not present, there is a swapin_readahead which tries to
readahead aligned 1 << clusters,(I didnt get that.) before doing a
read_swapcache,to get a page. Some of the routines call handle_mm_fault to fault
in the page to tasks virtual address space. One such routine is map_user_kiobuf
which uses a kiobuf to force in the pages to user space. Try reading it,because
sometimes you might have to use kiobuf,for mapping vmalloced pages to
user_space,supposing you define your own page_fault_handler,do_no_page. If you
want to define your own page_fault_handler,for mapping kernel_memory allocated
using kmalloc or vmalloc to user_space,then you should be prepared to look up
the page tables.For kmalloc cases you can use remap_page_range,but be aware of
the fact that remap_page_range only works with page_reserved cases. It doesn
work if the page is not reserved.(check out remap_pte_range in memory.c). So you
are better off,faulting in 1 page at a time,in case of a page_fault exception. I
have some sample codes,but they are there in kernelnewbies.org, mapping a device
section. vmalloc case is not covered over there. For vmalloc cases,you have to
look up kernel Page tables for tracking the page. The reason being-Vmalloc
virtual_addresses are contiguous in space,but they are not physically
contiguous.vmalloc addresses lie after the end of Physical Memory.(8 MEM HOLE
before vmalloc starts). Hence you should go about tracing the pte_entry for
those virtual_addresses in the Kernels Page tables. You can do for example :
get_page : {
pgd_t *pgd; pmd_t *pmd; pte_t *pte;
struct page *page = NOPAGE_SIGBUS;
pgd = pgd_offset_k(address) ; //pgd_offset_k takes care of passing init_mm.
if(! pgd_none(*pgd) ) {
pmd = pmd_offset(pgd,address);
if(! pmd_none(*pmd) ) {
pte = pte_offset(pmd,address);
if(pte_present(*pte) ) {
page = pte_page(*pte); //get the page
}
}
}
return page;
}
- « first
- ‹ previous
- of 24
- next ›
- last »