| From ba3e981abb3d0a1c9b6d7d8669964445dd0481fe Mon Sep 17 00:00:00 2001 |
| From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> |
| Date: Fri, 13 Mar 2020 15:18:42 +0530 |
| Subject: [PATCH] powerpc/hash64/devmap: Use H_PAGE_THP_HUGE when setting up |
| huge devmap PTE entries |
| |
| commit 36b78402d97a3b9aeab136feb9b00d8647ec2c20 upstream. |
| |
| H_PAGE_THP_HUGE is used to differentiate between a THP hugepage and |
| hugetlb hugepage entries. The difference is WRT how we handle hash |
| fault on these address. THP address enables MPSS in segments. We want |
| to manage devmap hugepage entries similar to THP pt entries. Hence use |
| H_PAGE_THP_HUGE for devmap huge PTE entries. |
| |
| With current code while handling hash PTE fault, we do set is_thp = |
| true when finding devmap PTE huge PTE entries. |
| |
| Current code also does the below sequence we setting up huge devmap |
| entries. |
| |
| entry = pmd_mkhuge(pfn_t_pmd(pfn, prot)); |
| if (pfn_t_devmap(pfn)) |
| entry = pmd_mkdevmap(entry); |
| |
| In that case we would find both H_PAGE_THP_HUGE and PAGE_DEVMAP set |
| for huge devmap PTE entries. This results in false positive error like |
| below. |
| |
| kernel BUG at /home/kvaneesh/src/linux/mm/memory.c:4321! |
| Oops: Exception in kernel mode, sig: 5 [#1] |
| LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries |
| Modules linked in: |
| CPU: 56 PID: 67996 Comm: t_mmap_dio Not tainted 5.6.0-rc4-59640-g371c804dedbc #128 |
| .... |
| NIP [c00000000044c9e4] __follow_pte_pmd+0x264/0x900 |
| LR [c0000000005d45f8] dax_writeback_one+0x1a8/0x740 |
| Call Trace: |
| str_spec.74809+0x22ffb4/0x2d116c (unreliable) |
| dax_writeback_one+0x1a8/0x740 |
| dax_writeback_mapping_range+0x26c/0x700 |
| ext4_dax_writepages+0x150/0x5a0 |
| do_writepages+0x68/0x180 |
| __filemap_fdatawrite_range+0x138/0x180 |
| file_write_and_wait_range+0xa4/0x110 |
| ext4_sync_file+0x370/0x6e0 |
| vfs_fsync_range+0x70/0xf0 |
| sys_msync+0x220/0x2e0 |
| system_call+0x5c/0x68 |
| |
| This is because our pmd_trans_huge check doesn't exclude _PAGE_DEVMAP. |
| |
| To make this all consistent, update pmd_mkdevmap to set |
| H_PAGE_THP_HUGE and pmd_trans_huge check now excludes _PAGE_DEVMAP |
| correctly. |
| |
| Fixes: ebd31197931d ("powerpc/mm: Add devmap support for ppc64") |
| Cc: stable@vger.kernel.org # v4.13+ |
| Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Link: https://lore.kernel.org/r/20200313094842.351830-1-aneesh.kumar@linux.ibm.com |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h |
| index 8fd8599c9395..3f9ae3585ab9 100644 |
| --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h |
| +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h |
| @@ -156,6 +156,12 @@ extern pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm, |
| extern int hash__has_transparent_hugepage(void); |
| #endif |
| |
| +static inline pmd_t hash__pmd_mkdevmap(pmd_t pmd) |
| +{ |
| + BUG(); |
| + return pmd; |
| +} |
| + |
| #endif /* !__ASSEMBLY__ */ |
| |
| #endif /* _ASM_POWERPC_BOOK3S_64_HASH_4K_H */ |
| diff --git a/arch/powerpc/include/asm/book3s/64/hash-64k.h b/arch/powerpc/include/asm/book3s/64/hash-64k.h |
| index d1d9177d9ebd..0729c034e56f 100644 |
| --- a/arch/powerpc/include/asm/book3s/64/hash-64k.h |
| +++ b/arch/powerpc/include/asm/book3s/64/hash-64k.h |
| @@ -246,7 +246,7 @@ static inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array, |
| */ |
| static inline int hash__pmd_trans_huge(pmd_t pmd) |
| { |
| - return !!((pmd_val(pmd) & (_PAGE_PTE | H_PAGE_THP_HUGE)) == |
| + return !!((pmd_val(pmd) & (_PAGE_PTE | H_PAGE_THP_HUGE | _PAGE_DEVMAP)) == |
| (_PAGE_PTE | H_PAGE_THP_HUGE)); |
| } |
| |
| @@ -272,6 +272,12 @@ extern pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm, |
| unsigned long addr, pmd_t *pmdp); |
| extern int hash__has_transparent_hugepage(void); |
| #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
| + |
| +static inline pmd_t hash__pmd_mkdevmap(pmd_t pmd) |
| +{ |
| + return __pmd(pmd_val(pmd) | (_PAGE_PTE | H_PAGE_THP_HUGE | _PAGE_DEVMAP)); |
| +} |
| + |
| #endif /* __ASSEMBLY__ */ |
| |
| #endif /* _ASM_POWERPC_BOOK3S_64_HASH_64K_H */ |
| diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h |
| index ccf00a8b98c6..daae0757807b 100644 |
| --- a/arch/powerpc/include/asm/book3s/64/pgtable.h |
| +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h |
| @@ -1295,7 +1295,9 @@ extern void serialize_against_pte_lookup(struct mm_struct *mm); |
| |
| static inline pmd_t pmd_mkdevmap(pmd_t pmd) |
| { |
| - return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP)); |
| + if (radix_enabled()) |
| + return radix__pmd_mkdevmap(pmd); |
| + return hash__pmd_mkdevmap(pmd); |
| } |
| |
| static inline int pmd_devmap(pmd_t pmd) |
| diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h |
| index 574eca33f893..0efada5b4600 100644 |
| --- a/arch/powerpc/include/asm/book3s/64/radix.h |
| +++ b/arch/powerpc/include/asm/book3s/64/radix.h |
| @@ -257,6 +257,11 @@ extern pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm, |
| extern int radix__has_transparent_hugepage(void); |
| #endif |
| |
| +static inline pmd_t radix__pmd_mkdevmap(pmd_t pmd) |
| +{ |
| + return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP)); |
| +} |
| + |
| extern int __meminit radix__vmemmap_create_mapping(unsigned long start, |
| unsigned long page_size, |
| unsigned long phys); |
| -- |
| 2.7.4 |
| |