diff options
author | Chris Metcalf | 2013-08-12 15:08:09 -0400 |
---|---|---|
committer | Chris Metcalf | 2013-09-03 14:52:13 -0400 |
commit | 640710a33b54de8d90ae140ef633ed0feba76a75 (patch) | |
tree | c58e0f7b36fef258674ddf9d5425608d3b5a430e /arch/tile/mm | |
parent | 49cf78ef7bb34833496d59b6dfe84ae51b1ab097 (diff) |
tile: add virt_to_kpte() API and clean up and document behavior
We use virt_to_pte(NULL, va) a lot, which isn't very obvious.
I added virt_to_kpte(va) as a more obvious wrapper function,
that also validates the va as being a kernel adddress.
And, I fixed the semantics of virt_to_pte() so that we handle
the pud and pmd the same way, and we now document the fact that
we handle the final pte level differently.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/mm')
-rw-r--r-- | arch/tile/mm/homecache.c | 6 | ||||
-rw-r--r-- | arch/tile/mm/init.c | 4 | ||||
-rw-r--r-- | arch/tile/mm/pgtable.c | 22 |
3 files changed, 25 insertions, 7 deletions
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c index df46a2d5bdf0..e3ee55b0327a 100644 --- a/arch/tile/mm/homecache.c +++ b/arch/tile/mm/homecache.c @@ -200,7 +200,7 @@ void homecache_finv_map_page(struct page *page, int home) #else va = __fix_to_virt(FIX_HOMECACHE_BEGIN + smp_processor_id()); #endif - ptep = virt_to_pte(NULL, (unsigned long)va); + ptep = virt_to_kpte(va); pte = pfn_pte(page_to_pfn(page), PAGE_KERNEL); __set_pte(ptep, pte_set_home(pte, home)); homecache_finv_page_va((void *)va, home); @@ -385,7 +385,7 @@ int page_home(struct page *page) return initial_page_home(); } else { unsigned long kva = (unsigned long)page_address(page); - return pte_to_home(*virt_to_pte(NULL, kva)); + return pte_to_home(*virt_to_kpte(kva)); } } EXPORT_SYMBOL(page_home); @@ -404,7 +404,7 @@ void homecache_change_page_home(struct page *page, int order, int home) NULL, 0); for (i = 0; i < pages; ++i, kva += PAGE_SIZE) { - pte_t *ptep = virt_to_pte(NULL, kva); + pte_t *ptep = virt_to_kpte(kva); pte_t pteval = *ptep; BUG_ON(!pte_present(pteval) || pte_huge(pteval)); __set_pte(ptep, pte_set_home(pteval, home)); diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c index c6d21601ec4d..c8f58c12866d 100644 --- a/arch/tile/mm/init.c +++ b/arch/tile/mm/init.c @@ -951,7 +951,7 @@ static void mark_w1data_ro(void) BUG_ON((addr & (PAGE_SIZE-1)) != 0); for (; addr <= (unsigned long)__w1data_end - 1; addr += PAGE_SIZE) { unsigned long pfn = kaddr_to_pfn((void *)addr); - pte_t *ptep = virt_to_pte(NULL, addr); + pte_t *ptep = virt_to_kpte(addr); BUG_ON(pte_huge(*ptep)); /* not relevant for kdata_huge */ set_pte_at(&init_mm, addr, ptep, pfn_pte(pfn, PAGE_KERNEL_RO)); } @@ -997,7 +997,7 @@ static void free_init_pages(char *what, unsigned long begin, unsigned long end) */ int pfn = kaddr_to_pfn((void *)addr); struct page *page = pfn_to_page(pfn); - pte_t *ptep = virt_to_pte(NULL, addr); + pte_t *ptep = virt_to_kpte(addr); if (!initfree) { /* * If debugging page accesses then do not free diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c index 300443389671..2deaddf3e01f 100644 --- a/arch/tile/mm/pgtable.c +++ b/arch/tile/mm/pgtable.c @@ -325,6 +325,17 @@ void ptep_set_wrprotect(struct mm_struct *mm, #endif +/* + * Return a pointer to the PTE that corresponds to the given + * address in the given page table. A NULL page table just uses + * the standard kernel page table; the preferred API in this case + * is virt_to_kpte(). + * + * The returned pointer can point to a huge page in other levels + * of the page table than the bottom, if the huge page is present + * in the page table. For bottom-level PTEs, the returned pointer + * can point to a PTE that is either present or not. + */ pte_t *virt_to_pte(struct mm_struct* mm, unsigned long addr) { pgd_t *pgd; @@ -341,14 +352,21 @@ pte_t *virt_to_pte(struct mm_struct* mm, unsigned long addr) if (pud_huge_page(*pud)) return (pte_t *)pud; pmd = pmd_offset(pud, addr); - if (pmd_huge_page(*pmd)) - return (pte_t *)pmd; if (!pmd_present(*pmd)) return NULL; + if (pmd_huge_page(*pmd)) + return (pte_t *)pmd; return pte_offset_kernel(pmd, addr); } EXPORT_SYMBOL(virt_to_pte); +pte_t *virt_to_kpte(unsigned long kaddr) +{ + BUG_ON(kaddr < PAGE_OFFSET); + return virt_to_pte(NULL, kaddr); +} +EXPORT_SYMBOL(virt_to_kpte); + pgprot_t set_remote_cache_cpu(pgprot_t prot, int cpu) { unsigned int width = smp_width; |