| From 30efc336189630505b06cc636f79656c66459b1e Mon Sep 17 00:00:00 2001 |
| From: Tom Hromatka <tom.hromatka@oracle.com> |
| Date: Fri, 31 Mar 2017 16:31:42 -0600 |
| Subject: [PATCH] sparc64: Fix kernel panic due to erroneous #ifdef surrounding |
| pmd_write() |
| |
| commit 9ae34dbd8afd790cb5f52467e4f816434379eafa upstream. |
| |
| This commit moves sparc64's prototype of pmd_write() outside |
| of the CONFIG_TRANSPARENT_HUGEPAGE ifdef. |
| |
| In 2013, commit a7b9403f0e6d ("sparc64: Encode huge PMDs using PTE |
| encoding.") exposed a path where pmd_write() could be called without |
| CONFIG_TRANSPARENT_HUGEPAGE defined. This can result in the panic below. |
| |
| The diff is awkward to read, but the changes are straightforward. |
| pmd_write() was moved outside of #ifdef CONFIG_TRANSPARENT_HUGEPAGE. |
| Also, __HAVE_ARCH_PMD_WRITE was defined. |
| |
| kernel BUG at include/asm-generic/pgtable.h:576! |
| \|/ ____ \|/ |
| "@'/ .. \`@" |
| /_| \__/ |_\ |
| \__U_/ |
| oracle_8114_cdb(8114): Kernel bad sw trap 5 [#1] |
| CPU: 120 PID: 8114 Comm: oracle_8114_cdb Not tainted |
| 4.1.12-61.7.1.el6uek.rc1.sparc64 #1 |
| task: fff8400700a24d60 ti: fff8400700bc4000 task.ti: fff8400700bc4000 |
| TSTATE: 0000004411e01607 TPC: 00000000004609f8 TNPC: 00000000004609fc Y: |
| 00000005 Not tainted |
| TPC: <gup_huge_pmd+0x198/0x1e0> |
| g0: 000000000001c000 g1: 0000000000ef3954 g2: 0000000000000000 g3: 0000000000000001 |
| g4: fff8400700a24d60 g5: fff8001fa5c10000 g6: fff8400700bc4000 g7: 0000000000000720 |
| o0: 0000000000bc5058 o1: 0000000000000240 o2: 0000000000006000 o3: 0000000000001c00 |
| o4: 0000000000000000 o5: 0000048000080000 sp: fff8400700bc6ab1 ret_pc: 00000000004609f0 |
| RPC: <gup_huge_pmd+0x190/0x1e0> |
| l0: fff8400700bc74fc l1: 0000000000020000 l2: 0000000000002000 l3: 0000000000000000 |
| l4: fff8001f93250950 l5: 000000000113f800 l6: 0000000000000004 l7: 0000000000000000 |
| i0: fff8400700ca46a0 i1: bd0000085e800453 i2: 000000026a0c4000 i3: 000000026a0c6000 |
| i4: 0000000000000001 i5: fff800070c958de8 i6: fff8400700bc6b61 i7: 0000000000460dd0 |
| I7: <gup_pud_range+0x170/0x1a0> |
| Call Trace: |
| [0000000000460dd0] gup_pud_range+0x170/0x1a0 |
| [0000000000460e84] get_user_pages_fast+0x84/0x120 |
| [00000000006f5a18] iov_iter_get_pages+0x98/0x240 |
| [00000000005fa744] do_direct_IO+0xf64/0x1e00 |
| [00000000005fbbc0] __blockdev_direct_IO+0x360/0x15a0 |
| [00000000101f74fc] ext4_ind_direct_IO+0xdc/0x400 [ext4] |
| [00000000101af690] ext4_ext_direct_IO+0x1d0/0x2c0 [ext4] |
| [00000000101af86c] ext4_direct_IO+0xec/0x220 [ext4] |
| [0000000000553bd4] generic_file_read_iter+0x114/0x140 |
| [00000000005bdc2c] __vfs_read+0xac/0x100 |
| [00000000005bf254] vfs_read+0x54/0x100 |
| [00000000005bf368] SyS_pread64+0x68/0x80 |
| |
| Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h |
| index 1fb317fbc0b3..b6802b978140 100644 |
| --- a/arch/sparc/include/asm/pgtable_64.h |
| +++ b/arch/sparc/include/asm/pgtable_64.h |
| @@ -673,26 +673,27 @@ static inline unsigned long pmd_pfn(pmd_t pmd) |
| return pte_pfn(pte); |
| } |
| |
| -#ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| -static inline unsigned long pmd_dirty(pmd_t pmd) |
| +#define __HAVE_ARCH_PMD_WRITE |
| +static inline unsigned long pmd_write(pmd_t pmd) |
| { |
| pte_t pte = __pte(pmd_val(pmd)); |
| |
| - return pte_dirty(pte); |
| + return pte_write(pte); |
| } |
| |
| -static inline unsigned long pmd_young(pmd_t pmd) |
| +#ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| +static inline unsigned long pmd_dirty(pmd_t pmd) |
| { |
| pte_t pte = __pte(pmd_val(pmd)); |
| |
| - return pte_young(pte); |
| + return pte_dirty(pte); |
| } |
| |
| -static inline unsigned long pmd_write(pmd_t pmd) |
| +static inline unsigned long pmd_young(pmd_t pmd) |
| { |
| pte_t pte = __pte(pmd_val(pmd)); |
| |
| - return pte_write(pte); |
| + return pte_young(pte); |
| } |
| |
| static inline unsigned long pmd_trans_huge(pmd_t pmd) |
| -- |
| 2.12.0 |
| |