I am working with linux kernel 2.6.38 and have a question about two fields of a vm_area_struct, vm_flags and vm_page_prot. If I mmap private anonymous memory to be readable and writable, and then I print out the two fields of the created vm_area_struct, I see that the low 8 bits of vm_flags are 0x73 and the low 8 bits of vm_page_prot are 0x25. I am running x86 32-bit, and my constants are
VM_READ=0x01
VM_WRITE=0x02
VM_EXEC=0x04
Thus, it appears my vm_flags says the memory is read/write but the vm_page_prot says it is only readable (the executable flag is meaningless on x86). My understanding is that vm_page_prot is supposed to reflect the protection of page table entries of pages in the VM region. As I go onto read/write memory in the mmaped area in userspace, the page faulting mechanism work correctly, setting the PTE’s of the appropriate pages. Some pages (if I only read from them) are mapped to the special zero page frame with the PTE set to read only while other pages that are written to have the PTE set to read/write. This is expected behavior…in fact, from mm/memory.c:
static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, pte_t *page_table, pmd_t *pmd,
unsigned int flags)
{
...
entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), vma->vm_page_prot));
...
}
My question is what determines vm_page_prot. My guess is that vm_page_prot is somehow a most restrictive combination (intersection) of all page permissions within the VM region, whereas vm_flags actually describes the true intentions of how the memory should act.
Does anyone have any good articles on what the exact purposes/differences of the two fields are?
Notice the C types of these two fields.
vm_page_prot‘s type ispgprot_t, which is a arch level data type, meaning it can be applied directly to the PTEs of the underlying architecture. On x86 32-bit, this field stores the content of the proper protection bits for the PTEs of the VMA.vm_flags, on the contrary, is an arch-independent field, whose bits are defined inlinux/mm.h. There are numerousVM_* bits, and they extend heavily over just the simple flags of READ, WRITE, and EXEC.So it looks to me that
vm_page_protis a form of a cached conversion fromvm_flags, which stores the proper protection bits for the underlying architecture. Notice that in many areas where a PTE is formed in the VMA,pgprot_tis being used almost directly.