summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.22/0008-thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.22/0008-thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit.patch')
-rw-r--r--recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.22/0008-thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit.patch125
1 files changed, 125 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.22/0008-thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.22/0008-thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit.patch
new file mode 100644
index 00000000..79be9e0f
--- /dev/null
+++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.22/0008-thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit.patch
@@ -0,0 +1,125 @@
1From dcfb4634621189a74522dee4d0dab8b5c1786b02 Mon Sep 17 00:00:00 2001
2From: Andrea Arcangeli <aarcange@redhat.com>
3Date: Wed, 20 Jun 2012 12:52:57 -0700
4Subject: [PATCH 08/46] thp: avoid atomic64_read in pmd_read_atomic for 32bit
5 PAE
6
7commit e4eed03fd06578571c01d4f1478c874bb432c815 upstream.
8
9In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the
10mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under
11Xen.
12
13So instead of dealing only with "consistent" pmdvals in
14pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually
15simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals
16where the low 32bit and high 32bit could be inconsistent (to avoid having
17to use cmpxchg8b).
18
19The only guarantee we get from pmd_read_atomic is that if the low part of
20the pmd was found null, the high part will be null too (so the pmd will be
21considered unstable). And if the low part of the pmd is found "stable"
22later, then it means the whole pmd was read atomically (because after a
23pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore,
24and we read the high part after the low part).
25
26In the 32bit PAE x86 case, it is enough to read the low part of the pmdval
27atomically to declare the pmd as "stable" and that's true for THP and no
28THP, furthermore in the THP case we also have a barrier() that will
29prevent any inconsistent pmdvals to be cached by a later re-read of the
30*pmd.
31
32Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
33Cc: Jonathan Nieder <jrnieder@gmail.com>
34Cc: Ulrich Obergfell <uobergfe@redhat.com>
35Cc: Mel Gorman <mgorman@suse.de>
36Cc: Hugh Dickins <hughd@google.com>
37Cc: Larry Woodman <lwoodman@redhat.com>
38Cc: Petr Matousek <pmatouse@redhat.com>
39Cc: Rik van Riel <riel@redhat.com>
40Cc: Jan Beulich <jbeulich@suse.com>
41Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
42Tested-by: Andrew Jones <drjones@redhat.com>
43Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
44Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
45Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
46---
47 arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++++++-------------
48 include/asm-generic/pgtable.h | 10 ++++++++++
49 2 files changed, 27 insertions(+), 13 deletions(-)
50
51diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
52index 43876f1..cb00ccc 100644
53--- a/arch/x86/include/asm/pgtable-3level.h
54+++ b/arch/x86/include/asm/pgtable-3level.h
55@@ -47,16 +47,26 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
56 * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
57 * operations.
58 *
59- * Without THP if the mmap_sem is hold for reading, the
60- * pmd can only transition from null to not null while pmd_read_atomic runs.
61- * So there's no need of literally reading it atomically.
62+ * Without THP if the mmap_sem is hold for reading, the pmd can only
63+ * transition from null to not null while pmd_read_atomic runs. So
64+ * we can always return atomic pmd values with this function.
65 *
66 * With THP if the mmap_sem is hold for reading, the pmd can become
67- * THP or null or point to a pte (and in turn become "stable") at any
68- * time under pmd_read_atomic, so it's mandatory to read it atomically
69- * with cmpxchg8b.
70+ * trans_huge or none or point to a pte (and in turn become "stable")
71+ * at any time under pmd_read_atomic. We could read it really
72+ * atomically here with a atomic64_read for the THP enabled case (and
73+ * it would be a whole lot simpler), but to avoid using cmpxchg8b we
74+ * only return an atomic pmdval if the low part of the pmdval is later
75+ * found stable (i.e. pointing to a pte). And we're returning a none
76+ * pmdval if the low part of the pmd is none. In some cases the high
77+ * and low part of the pmdval returned may not be consistent if THP is
78+ * enabled (the low part may point to previously mapped hugepage,
79+ * while the high part may point to a more recently mapped hugepage),
80+ * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part
81+ * of the pmd to be read atomically to decide if the pmd is unstable
82+ * or not, with the only exception of when the low part of the pmd is
83+ * zero in which case we return a none pmd.
84 */
85-#ifndef CONFIG_TRANSPARENT_HUGEPAGE
86 static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
87 {
88 pmdval_t ret;
89@@ -74,12 +84,6 @@ static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
90
91 return (pmd_t) { ret };
92 }
93-#else /* CONFIG_TRANSPARENT_HUGEPAGE */
94-static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
95-{
96- return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
97-}
98-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
99
100 static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
101 {
102diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
103index 831924a..bc00876 100644
104--- a/include/asm-generic/pgtable.h
105+++ b/include/asm-generic/pgtable.h
106@@ -484,6 +484,16 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
107 /*
108 * The barrier will stabilize the pmdval in a register or on
109 * the stack so that it will stop changing under the code.
110+ *
111+ * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE,
112+ * pmd_read_atomic is allowed to return a not atomic pmdval
113+ * (for example pointing to an hugepage that has never been
114+ * mapped in the pmd). The below checks will only care about
115+ * the low part of the pmd with 32bit PAE x86 anyway, with the
116+ * exception of pmd_none(). So the important thing is that if
117+ * the low part of the pmd is found null, the high part will
118+ * be also null or the pmd_none() check below would be
119+ * confused.
120 */
121 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
122 barrier();
123--
1241.7.10
125