Reputation: 45
I want to use the pagefault handler of my struct vm_area_struct *
to map a physical page to user space.
Here is how I proceed:
alloc_page(GFP_USER)
during the module initialization (I tried various GFP).struct vm_area_struct
, set a custom pagefault handler, and attach the vma
to current->mm
.When a page fault occurs:
vmf->page
to the page I previously allocated and return 0.The result is that every virtual page in the vma
should be mapped to the same physical page after a page fault.
But here is what I noticed:
get_user_pages
in my kernel module to get the page (instead of using my global variable), I get a different physical address than the global page variable. I print the address using page_to_phys(page)
. Writing to this page is reflected in my user-space program.All of this is done in the page fault handler by the way.
How can this curious behavior be explained?
To access the page from kernel space, I'm using kmap_atomic
and kunmap_atomic
.
Upvotes: 2
Views: 1344
Reputation: 68
This is due to the copy-on-write mechanism.
After your page fault handler runs, the page you returned in vmf->page
is copied to a newly allocated page. This is why your changes in user-space are not reflected in your kernel module.
The page you were trying to read from in the kernel is not the one that was really mapped in your user-space process.
You can refer to the do_cow_fault
function in mm/memory.c
.
Upvotes: 1