Changes based on review comments for PAT pfnmap tracking
Subsystems (6)
PATCH 2/5 x86 PAT: Modify follow_phys to return phys_addr prot and return value
In reply to [email protected]follow_phys does similar things as follow_pfnmap_pte. Make a minor change to follow_phys so that it can be used in place of follow_pfnmap_pte. Physical address return value with 0 as error return does not work in follow_phys as the actual physical address 0 mapping may exist in pte.
--- include/linux/mm.h | 2 ++ mm/memory.c | 31 ++++++++++++++----------------- 2 files changed, 16 insertions(+), 17 deletions(-)
include/linux/mm.h +2 -0
@@ -804,6 +804,8 @@ int copy_page_range(struct mm_struct *ds struct vm_area_struct *vma);void unmap_mapping_range (struct address_space *mapping,loff_t const holebegin,loff_t const holelen,int even_cows); +int follow_phys (struct vm_area_struct *vma,unsigned long address, +unsigned int flags,unsigned long *prot,resource_size_t *phys);int generic_access_phys (struct vm_area_struct *vma,unsigned long addr,void *buf,int len,int write);
mm/memory.c +14 -17
@@ -2981,9 +2981,9 @@ int in_gate_area_no_task(unsigned long a#endif /* __HAVE_ARCH_GATE_AREA */ #ifdef CONFIG_HAVE_IOREMAP_PROT -static resource_size_t follow_phys (struct vm_area_struct *vma, -unsigned long address,unsigned int flags, -unsigned long *prot) +int follow_phys (struct vm_area_struct *vma, +unsigned long address,unsigned int flags, +unsigned long *prot,resource_size_t *phys) {pgd_t *pgd;pud_t *pud;
@@ -2992,24 +2992,26 @@ static resource_size_t follow_phys(strucspinlock_t *ptl;resource_size_t phys_addr =0 ;struct mm_struct *mm = vma->vm_mm; +int ret = -EINVAL ; -VM_BUG_ON (!(vma->vm_flags & (VM_IO |VM_PFNMAP ))); +if (!(vma->vm_flags & (VM_IO |VM_PFNMAP ))) + goto out; pgd =pgd_offset (mm, address);if (pgd_none (*pgd) ||unlikely (pgd_bad (*pgd))) - goto no_page_table; + goto out; pud =pud_offset (pgd, address);if (pud_none (*pud) ||unlikely (pud_bad (*pud))) - goto no_page_table; + goto out; pmd =pmd_offset (pud, address);if (pmd_none (*pmd) ||unlikely (pmd_bad (*pmd))) - goto no_page_table; + goto out;/* We cannot handle huge page PFN maps. Luckily they don't exist. */ if (pmd_huge (*pmd)) - goto no_page_table; + goto out; ptep =pte_offset_map_lock (mm, pmd, address, &ptl);if (!ptep)
@@ -3024,13 +3026,13 @@ static resource_size_t follow_phys(struc phys_addr <<=PAGE_SHIFT ;/* Shift here to avoid overflow on PAE */ *prot =pgprot_val (pte_pgprot (pte)); + *phys = phys_addr; + ret =0 ; unlock:pte_unmap_unlock (ptep, ptl); out: -return phys_addr; -no_page_table: -return 0 ; +return ret; } int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
@@ -3041,12 +3043,7 @@ int generic_access_phys(struct vm_area_svoid *maddr;int offset = addr & (PAGE_SIZE -1 ); -if (!(vma->vm_flags & (VM_IO |VM_PFNMAP ))) -return -EINVAL ; - - phys_addr =follow_phys (vma, addr, write, &prot); - -if (!phys_addr) +if (follow_phys (vma, addr, write, &prot, &phys_addr))return -EINVAL ; maddr =ioremap_prot (phys_addr,PAGE_SIZE , prot);
PATCH 3/5 x86 PAT: remove follow_pfnmap_pte in favor of follow_phys
In reply to [email protected]Replace follow_pfnmap_pte in pat code with follow_phys. follow_phys lso returns protection eliminating the need of pte_pgprot call. Using follow_phys also eliminates the need for pte_pa.
--- arch/x86/include/asm/pgtable.h | 5 ---- arch/x86/mm/pat.c | 30 ++++++++++------------------ include/linux/mm.h | 3 -- mm/memory.c | 43 ----------------------------------------- 4 files changed, 11 insertions(+), 70 deletions(-)
include/linux/mm.h +0 -3
@@ -1239,9 +1239,6 @@ struct page *follow_page(struct vm_area_#define FOLL_GET 0x04/* do get_page on page */ #define FOLL_ANON 0x08/* give ZERO_PAGE if no pgtable */ -int follow_pfnmap_pte (struct vm_area_struct *vma, -unsigned long address,pte_t *ret_ptep); -typedef int (*pte_fn_t )(pte_t *pte,pgtable_t token,unsigned long addr,void *data); extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
mm/memory.c +0 -43
49 lines not on this page · raw message
arch/x86/mm/pat.c +11 -19
@@ -685,8 +685,7 @@ int track_pfn_vma_copy(struct vm_area_stint retval =0 ;unsigned long i, j;u64 paddr; -pgprot_t prot; -pte_t pte; +unsigned long prot;unsigned long vma_start = vma->vm_start;unsigned long vma_end = vma->vm_end;unsigned long vma_size = vma_end - vma_start;
@@ -696,26 +695,22 @@ int track_pfn_vma_copy(struct vm_area_stif (is_linear_pfn_mapping (vma)) {/* -* reserve the whole chunk starting from vm_pgoff, -* But, we have to get the protection from pte. +* reserve the whole chunk covered by vma. We need the +* starting address and protection from pte. */ -if (follow_pfnmap_pte (vma, vma_start, &pte)) { +if (follow_phys (vma, vma_start,0 , &prot, &paddr)) {WARN_ON_ONCE (1 ); -return -1 ; +return -EINVAL ; } - prot =pte_pgprot (pte); - paddr = (u64 )vma->vm_pgoff <<PAGE_SHIFT ; -return reserve_pfn_range (paddr, vma_size, prot); +return reserve_pfn_range (paddr, vma_size,__pgprot (prot)); }/* reserve entire vma page by page, using pfn and prot from pte */ for (i =0 ; i < vma_size; i +=PAGE_SIZE ) { -if (follow_pfnmap_pte (vma, vma_start + i, &pte)) +if (follow_phys (vma, vma_start + i,0 , &prot, &paddr))continue ; - paddr =pte_pa (pte); - prot =pte_pgprot (pte); - retval =reserve_pfn_range (paddr,PAGE_SIZE , prot); + retval =reserve_pfn_range (paddr,PAGE_SIZE ,__pgprot (prot));if (retval) goto cleanup_ret; }
@@ -724,10 +719,9 @@ int track_pfn_vma_copy(struct vm_area_st cleanup_ret:/* Reserve error: Cleanup partial reservation and return error */ for (j =0 ; j < i; j +=PAGE_SIZE ) { -if (follow_pfnmap_pte (vma, vma_start + j, &pte)) +if (follow_phys (vma, vma_start + j,0 , &prot, &paddr))continue ; - paddr =pte_pa (pte);free_pfn_range (paddr,PAGE_SIZE ); }
@@ -797,6 +791,7 @@ void untrack_pfn_vma(struct vm_area_stru {unsigned long i;u64 paddr; +unsigned long prot;unsigned long vma_start = vma->vm_start;unsigned long vma_end = vma->vm_end;unsigned long vma_size = vma_end - vma_start;
@@ -821,12 +816,9 @@ void untrack_pfn_vma(struct vm_area_stru }else {/* free entire vma, page by page, using the pfn from pte */ for (i =0 ; i < vma_size; i +=PAGE_SIZE ) { -pte_t pte; - -if (follow_pfnmap_pte (vma, vma_start + i, &pte)) +if (follow_phys (vma, vma_start + i,0 , &prot, &paddr))continue ; - paddr =pte_pa (pte);free_pfn_range (paddr,PAGE_SIZE ); } }
arch/x86/include/asm/pgtable.h +0 -5
@@ -230,11 +230,6 @@ static inline unsigned long pte_pfn(pte_return (pte_val (pte) &PTE_PFN_MASK ) >>PAGE_SHIFT ; } -static inline u64 pte_pa (pte_t pte) -{ -return pte_val (pte) &PTE_PFN_MASK ; -} -#define pte_page (pte) pfn_to_page(pte_pfn(pte))static inline int pmd_large (pmd_t pte)
PATCH 4/5 x86 PAT: Move track untrack pfnmap stubs to asm-generic
In reply to [email protected]Move the track and untrack pfn stub routines from memory.c to asm-generic. Also add unlikely to pfnmap related calls in fork and exit path.
--- arch/x86/include/asm/pgtable.h | 6 +---- include/asm-generic/pgtable.h | 46 +++++++++++++++++++++++++++++++++++++++ include/linux/mm.h | 6 ----- mm/memory.c | 48 +---------------------------------------- 4 files changed, 50 insertions(+), 56 deletions(-)
include/linux/mm.h +0 -6
@@ -163,12 +163,6 @@ static inline int is_pfn_mapping(structreturn (vma->vm_flags &VM_PFNMAP ); } -extern int track_pfn_vma_new (struct vm_area_struct *vma,pgprot_t prot, -unsigned long pfn,unsigned long size); -extern int track_pfn_vma_copy (struct vm_area_struct *vma); -extern void untrack_pfn_vma (struct vm_area_struct *vma,unsigned long pfn, -unsigned long size); -/* * vm_fault is filled by the the pagefault handler and passed to the vma's * ->fault function. The vma's ->fault is responsible for returning a bitmask
mm/memory.c +2 -46
66 lines not on this page · raw message
include/asm-generic/pgtable.h +46 -0
52 lines not on this page · raw message
arch/x86/include/asm/pgtable.h +2 -4
@@ -339,12 +339,10 @@ static inline pgprot_t pgprot_modify(pgp#define canon_pgprot (p) __pgprot(pgprot_val(p) & __supported_pte_mask) +#ifndef __ASSEMBLY__/* Indicate that x86 has its own track and untrack pfn vma functions */ -#define track_pfn_vma_new track_pfn_vma_new -#define track_pfn_vma_copy track_pfn_vma_copy -#define untrack_pfn_vma untrack_pfn_vma +#define __HAVE_PFNMAP_TRACKING -#ifndef __ASSEMBLY__#define __HAVE_PHYS_MEM_ACCESS_PROTstruct file ; pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
PATCH 5/5 x86 PAT: pfnmap documentation update changes
In reply to [email protected]Documentation updates as per Randy Dunlap's comments.
--- Documentation/x86/pat.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
Documentation/x86/pat.txt +5 -5
@@ -82,23 +82,23 @@ pci proc | -- | - Advanced APIs for drivers ------------------------- -A. Exporting pages to user with remap_pfn_range, io_remap_pfn_range, +A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range, vm_insert_pfn -Drivers wanting to export some pages to userspace, do it by using mmap +Drivers wanting to export some pages to userspace do it by using mmap interface and a combination of 1) pgprot_noncached() 2) io_remap_pfn_range() or remap_pfn_range() or vm_insert_pfn() -With pat support, a new API pgprot_writecombine is being added. So, driver can +With PAT support, a new API pgprot_writecombine is being added. So, drivers can continue to use the above sequence, with either pgprot_noncached() or pgprot_writecombine() in step 1, followed by step 2. In addition, step 2 internally tracks the region as UC or WC in memtype list in order to ensure no conflicting mapping. -Note that this set of APIs only work with IO (non RAM) regions. If driver -wants to export RAM region, it has to do set_memory_uc() or set_memory_wc() +Note that this set of APIs only works with IO (non RAM) regions. If driver +wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() as step 0 above and also track the usage of those pages and use set_memory_wb() before the page is freed to free pool.
cover Changes based on review comments for PAT pfnmap tracking
Incremental patches to address the review comments from Nick Piggin for v3 version of x86 PAT pfnmap changes patchset here
http://lkml.indiana.edu/hypermail/linux/kernel/0812.2/01330.html
PATCH 1/5 x86 PAT: clarify is_linear_pfn_mapping() interface
Incremental patches to address the review comments from Nick Piggin for v3 version of x86 PAT pfnmap changes patchset here
http://lkml.indiana.edu/hypermail/linux/kernel/0812.2/01330.html
This patch:
Clarify is_linear_pfn_mapping() and its usage.
It is used by x86 PAT code for performance reasons. Identifying pfnmap as linear over entire vma helps speedup reserve and free of memtype for the region.
--- include/linux/mm.h | 8 ++++++++ 1 file changed, 8 insertions(+)
include/linux/mm.h +8 -0
@@ -145,6 +145,14 @@ extern pgprot_t protection_map[16];#define FAULT_FLAG_WRITE 0x01/* Fault was a write access */ #define FAULT_FLAG_NONLINEAR 0x02/* Fault was via a nonlinear mapping */ +/* +* This interface is used by x86 PAT code to identify a pfn mapping that is +* linear over entire vma. This is to optimize PAT code that deals with +* marking the physical region with a particular prot. This is not for generic +* mm use. Note also that this check will not work if the pfn mapping is +* linear for a vma starting at physical address 0. In which case PAT code +* falls back to slow path of reserving physical range page by page. +*/ static inline int is_linear_pfn_mapping (struct vm_area_struct *vma) {return ((vma->vm_flags &VM_PFNMAP ) && vma->vm_pgoff);
Quoted 5 lines · [email protected] wrote:
Incremental patches to address the review comments from Nick Piggin for v3 version of x86 PAT pfnmap changes patchset here
http://lkml.indiana.edu/hypermail/linux/kernel/0812.2/01330.html
Applied to tip:x86/pat2, thanks!
-hpa
Quoted 4 lines · On Fri, Dec 19, 2008 at 01:47:25PM -0800, [email protected] wrote:
Incremental patches to address the review comments from Nick Piggin for v3 version of x86 PAT pfnmap changes patchset here
http://lkml.indiana.edu/hypermail/linux/kernel/0812.2/01330.html
Thanks. Feel free to put Reviewed-by: / Acked-by: Nick Piggin <[email protected]> on the generic mm patches which I reviewed after these changes if you like.