Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARC: Fix PAE40 boot failures due to PTE truncation

So a benign looking cleanup which macro'ized PAGE_SHIFT shifts turned
out to be bad (since it was done non-sensically across the board).

It caused boot failures with PAE40 as forced cast to (unsigned long)
from newly introduced virt_to_pfn() was causing truncatiion of the
(long long) pte/paddr values.

It is OK to use this in accessors dealing with kernel virtual address,
pointers etc, but not for PTE values themelves.

Fixes: cJ2ff5cf2735c ("ARC: mm: Use virt_to_pfn() for addr >> PAGE_SHIFT pattern)
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>

+14 -8
+8 -1
arch/arc/include/asm/page.h
··· 72 72 73 73 typedef pte_t * pgtable_t; 74 74 75 + /* 76 + * Use virt_to_pfn with caution: 77 + * If used in pte or paddr related macros, it could cause truncation 78 + * in PAE40 builds 79 + * As a rule of thumb, only use it in helpers starting with virt_ 80 + * You have been warned ! 81 + */ 75 82 #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 76 83 77 84 #define ARCH_PFN_OFFSET virt_to_pfn(CONFIG_LINUX_LINK_BASE) ··· 92 85 * virt here means link-address/program-address as embedded in object code. 93 86 * And for ARC, link-addr = physical address 94 87 */ 95 - #define __pa(vaddr) ((unsigned long)vaddr) 88 + #define __pa(vaddr) ((unsigned long)(vaddr)) 96 89 #define __va(paddr) ((void *)((unsigned long)(paddr))) 97 90 98 91 #define virt_to_page(kaddr) \
+6 -7
arch/arc/include/asm/pgtable.h
··· 278 278 #define pmd_present(x) (pmd_val(x)) 279 279 #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) 280 280 281 - #define pte_page(pte) \ 282 - (mem_map + virt_to_pfn(pte_val(pte) - CONFIG_LINUX_LINK_BASE)) 283 - 281 + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) 284 282 #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) 285 - #define pte_pfn(pte) virt_to_pfn(pte_val(pte)) 286 - #define pfn_pte(pfn, prot) (__pte(((pte_t)(pfn) << PAGE_SHIFT) | \ 287 - pgprot_val(prot))) 288 - #define __pte_index(addr) (virt_to_pfn(addr) & (PTRS_PER_PTE - 1)) 283 + #define pfn_pte(pfn, prot) (__pte(((pte_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) 284 + 285 + /* Don't use virt_to_pfn for macros below: could cause truncations for PAE40*/ 286 + #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) 287 + #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 289 288 290 289 /* 291 290 * pte_offset gets a @ptr to PMD entry (PGD in our 2-tier paging system)