| From 8ec327c454c5ce9b7ec1e8c87d0089edd69e9b4e Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 5 Nov 2021 08:54:03 +0100 |
| Subject: arm64: pgtable: make __pte_to_phys/__phys_to_pte_val inline functions |
| |
| From: Arnd Bergmann <arnd@arndb.de> |
| |
| [ Upstream commit c7c386fbc20262c1d911c615c65db6a58667d92c ] |
| |
| gcc warns about undefined behavior the vmalloc code when building |
| with CONFIG_ARM64_PA_BITS_52, when the 'idx++' in the argument to |
| __phys_to_pte_val() is evaluated twice: |
| |
| mm/vmalloc.c: In function 'vmap_pfn_apply': |
| mm/vmalloc.c:2800:58: error: operation on 'data->idx' may be undefined [-Werror=sequence-point] |
| 2800 | *pte = pte_mkspecial(pfn_pte(data->pfns[data->idx++], data->prot)); |
| | ~~~~~~~~~^~ |
| arch/arm64/include/asm/pgtable-types.h:25:37: note: in definition of macro '__pte' |
| 25 | #define __pte(x) ((pte_t) { (x) } ) |
| | ^ |
| arch/arm64/include/asm/pgtable.h:80:15: note: in expansion of macro '__phys_to_pte_val' |
| 80 | __pte(__phys_to_pte_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) |
| | ^~~~~~~~~~~~~~~~~ |
| mm/vmalloc.c:2800:30: note: in expansion of macro 'pfn_pte' |
| 2800 | *pte = pte_mkspecial(pfn_pte(data->pfns[data->idx++], data->prot)); |
| | ^~~~~~~ |
| |
| I have no idea why this never showed up earlier, but the safest |
| workaround appears to be changing those macros into inline functions |
| so the arguments get evaluated only once. |
| |
| Cc: Matthew Wilcox <willy@infradead.org> |
| Fixes: 75387b92635e ("arm64: handle 52-bit physical addresses in page table entries") |
| Signed-off-by: Arnd Bergmann <arnd@arndb.de> |
| Link: https://lore.kernel.org/r/20211105075414.2553155-1-arnd@kernel.org |
| Signed-off-by: Will Deacon <will@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/arm64/include/asm/pgtable.h | 12 +++++++++--- |
| 1 file changed, 9 insertions(+), 3 deletions(-) |
| |
| diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h |
| index a92a187ec8919..3a057d4279007 100644 |
| --- a/arch/arm64/include/asm/pgtable.h |
| +++ b/arch/arm64/include/asm/pgtable.h |
| @@ -54,9 +54,15 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; |
| * page table entry, taking care of 52-bit addresses. |
| */ |
| #ifdef CONFIG_ARM64_PA_BITS_52 |
| -#define __pte_to_phys(pte) \ |
| - ((pte_val(pte) & PTE_ADDR_LOW) | ((pte_val(pte) & PTE_ADDR_HIGH) << 36)) |
| -#define __phys_to_pte_val(phys) (((phys) | ((phys) >> 36)) & PTE_ADDR_MASK) |
| +static inline phys_addr_t __pte_to_phys(pte_t pte) |
| +{ |
| + return (pte_val(pte) & PTE_ADDR_LOW) | |
| + ((pte_val(pte) & PTE_ADDR_HIGH) << 36); |
| +} |
| +static inline pteval_t __phys_to_pte_val(phys_addr_t phys) |
| +{ |
| + return (phys | (phys >> 36)) & PTE_ADDR_MASK; |
| +} |
| #else |
| #define __pte_to_phys(pte) (pte_val(pte) & PTE_ADDR_MASK) |
| #define __phys_to_pte_val(phys) (phys) |
| -- |
| 2.33.0 |
| |