diff options
author | Tom Hromatka <tom.hromatka@oracle.com> | 2017-03-31 18:31:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-03 11:36:34 -0400 |
commit | 512d211207df2a6e7ef0fa5c402f0f9f39b1fe8d (patch) | |
tree | d21f3e0f566abd12a54d2f8d265b6d87bfe3a16a /arch/sparc/include | |
parent | 24870a79dad693214b21558388cb04dad6159aa3 (diff) |
sparc64: Fix kernel panic due to erroneous #ifdef surrounding pmd_write()
[ Upstream commit 9ae34dbd8afd790cb5f52467e4f816434379eafa ]
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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/sparc/include')
-rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 15 |
1 files changed, 8 insertions, 7 deletions
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) | |||
673 | return pte_pfn(pte); | 673 | return pte_pfn(pte); |
674 | } | 674 | } |
675 | 675 | ||
676 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 676 | #define __HAVE_ARCH_PMD_WRITE |
677 | static inline unsigned long pmd_dirty(pmd_t pmd) | 677 | static inline unsigned long pmd_write(pmd_t pmd) |
678 | { | 678 | { |
679 | pte_t pte = __pte(pmd_val(pmd)); | 679 | pte_t pte = __pte(pmd_val(pmd)); |
680 | 680 | ||
681 | return pte_dirty(pte); | 681 | return pte_write(pte); |
682 | } | 682 | } |
683 | 683 | ||
684 | static inline unsigned long pmd_young(pmd_t pmd) | 684 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
685 | static inline unsigned long pmd_dirty(pmd_t pmd) | ||
685 | { | 686 | { |
686 | pte_t pte = __pte(pmd_val(pmd)); | 687 | pte_t pte = __pte(pmd_val(pmd)); |
687 | 688 | ||
688 | return pte_young(pte); | 689 | return pte_dirty(pte); |
689 | } | 690 | } |
690 | 691 | ||
691 | static inline unsigned long pmd_write(pmd_t pmd) | 692 | static inline unsigned long pmd_young(pmd_t pmd) |
692 | { | 693 | { |
693 | pte_t pte = __pte(pmd_val(pmd)); | 694 | pte_t pte = __pte(pmd_val(pmd)); |
694 | 695 | ||
695 | return pte_write(pte); | 696 | return pte_young(pte); |
696 | } | 697 | } |
697 | 698 | ||
698 | static inline unsigned long pmd_trans_huge(pmd_t pmd) | 699 | static inline unsigned long pmd_trans_huge(pmd_t pmd) |