diff options
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.patch | 125 |
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 @@ | |||
1 | From dcfb4634621189a74522dee4d0dab8b5c1786b02 Mon Sep 17 00:00:00 2001 | ||
2 | From: Andrea Arcangeli <aarcange@redhat.com> | ||
3 | Date: Wed, 20 Jun 2012 12:52:57 -0700 | ||
4 | Subject: [PATCH 08/46] thp: avoid atomic64_read in pmd_read_atomic for 32bit | ||
5 | PAE | ||
6 | |||
7 | commit e4eed03fd06578571c01d4f1478c874bb432c815 upstream. | ||
8 | |||
9 | In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the | ||
10 | mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under | ||
11 | Xen. | ||
12 | |||
13 | So instead of dealing only with "consistent" pmdvals in | ||
14 | pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually | ||
15 | simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals | ||
16 | where the low 32bit and high 32bit could be inconsistent (to avoid having | ||
17 | to use cmpxchg8b). | ||
18 | |||
19 | The only guarantee we get from pmd_read_atomic is that if the low part of | ||
20 | the pmd was found null, the high part will be null too (so the pmd will be | ||
21 | considered unstable). And if the low part of the pmd is found "stable" | ||
22 | later, then it means the whole pmd was read atomically (because after a | ||
23 | pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore, | ||
24 | and we read the high part after the low part). | ||
25 | |||
26 | In the 32bit PAE x86 case, it is enough to read the low part of the pmdval | ||
27 | atomically to declare the pmd as "stable" and that's true for THP and no | ||
28 | THP, furthermore in the THP case we also have a barrier() that will | ||
29 | prevent any inconsistent pmdvals to be cached by a later re-read of the | ||
30 | *pmd. | ||
31 | |||
32 | Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> | ||
33 | Cc: Jonathan Nieder <jrnieder@gmail.com> | ||
34 | Cc: Ulrich Obergfell <uobergfe@redhat.com> | ||
35 | Cc: Mel Gorman <mgorman@suse.de> | ||
36 | Cc: Hugh Dickins <hughd@google.com> | ||
37 | Cc: Larry Woodman <lwoodman@redhat.com> | ||
38 | Cc: Petr Matousek <pmatouse@redhat.com> | ||
39 | Cc: Rik van Riel <riel@redhat.com> | ||
40 | Cc: Jan Beulich <jbeulich@suse.com> | ||
41 | Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com> | ||
42 | Tested-by: Andrew Jones <drjones@redhat.com> | ||
43 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | ||
44 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||
45 | Signed-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 | |||
51 | diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h | ||
52 | index 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 | { | ||
102 | diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h | ||
103 | index 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 | -- | ||
124 | 1.7.10 | ||
125 | |||