Robert Martin
Robert Martin

Reputation: 17157

How do I find the ptep for a given address?

I'm trying to write a function that write-protects every pte in a given vm_area_struct. What is the function that gives me the ptep for a given address? I have:

pte_t *ptep;
for (addr = start; addr < end; addr += PAGE_SIZE) {
    ptep = WHATS_THIS_FUNCTION_CALLED(addr);
    ptep_set_wrprotect(mm, addr, ptep);
}

What's the WHATS_THIS_FUNCTION_CALLED called?

Upvotes: 1

Views: 617

Answers (2)

Chris
Chris

Reputation: 2896

The short answer to your question is to use __get_locked_pte . However, I would advise against it since there are much better (efficient and fair in terms of resource contention) ways to accomplish your goal.

In linux, the typical idiom for traversing page tables is with a nested for loop four levels deep (four is the number of page table levels linux supports). For examples, see copy_page_range and apply_to_page_range in mm/memory.c. In fact, if you look closely at copy_page_range, it is called when forking from dup_mmap in kernel/fork.c. It operates on an entire vm_area_struct essentially.

You can replicate the idiom used in either of those functions. There are some caveats, however. For example, copy_page_range fully supports transparent hugepages (2.6.38) by using a completely separate copy_huge_pmd inside copy_pmd_range. Unless you want to write two separate functions (one for normal pages and one for transparent huge pages, see Gracefull fallback in Documentation/vm/transhuge.txt.

The point is that virtual memory in linux is very complicated, so be sure to completely understand every possible use case. follow_page in mm/memory.c should demonstrate how to cover all of your bases.

Upvotes: 1

Appleman1234
Appleman1234

Reputation: 16076

I believe you are looking for either the function virt_to_pte as defined here or your own re-implementation of it.

This function uses pte_offset_kernel(pmd_t * dir, unsigned long address) which takes a pmd (Page mid-level Directory) structure and an address , though one could also use pte_offset(pmd_t * dir, unsigned long address).

See Linux Device Drivers 3rd Edition Chapter 15 or Linux Device Drivers, 2nd Edition Chapter 13 mmap and DMA for further references.

Upvotes: 0

Related Questions