]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.arch/x86-fix-kmap-contig.patch
Disable build of xen kernel.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / x86-fix-kmap-contig.patch
1 From: Nick Piggin <npiggin@suse.de>
2 Subject: x86: contiguous kmap fix
3 References: bnc#449812
4 Patch-mainline: perhaps 2.6.30 (maybe .29)
5
6 The early fixmap pmd entry inserted at the very top of the KVA is casing the
7 subsequent fixmap mapping code to not provide physically linear pte pages over
8 the kmap atomic portion of the fixmap (which relies on said property to calculate
9 pte address).
10
11 This has caused weird boot failures in kmap_atomic much later in the boot
12 process (initial userspace faults) on a 32-bit PAE system with a larger number
13 of CPUs (smaller CPU counts tend not to run over into the next page so don't
14 show up the problem).
15
16 Solve this by attempting to clear out the page table, and copy any of its
17 entries to the new one. Also, add a bug if a nonlinear condition is encountered
18 and can't be resolved, which might save some hours of debugging if this fragile
19 scheme ever breaks again...
20
21 Signed-off-by: Nick Piggin <npiggin@suse.de>
22
23 Once we have such logic, we can also use it to eliminate the early ioremap
24 trickery around the page table setup for the fixmap area. This also fixes
25 potential issues with FIX_* entries sharing the leaf page table with the early
26 ioremap ones getting discarded by early_ioremap_clear() and not restored by
27 early_ioremap_reset(). It at once eliminates the temporary (and configuration,
28 namely NR_CPUS, dependent) unavailability of early fixed mappings during the
29 time the fixmap area page tables get constructed.
30
31 Finally, also replace the hard coded calculation of the initial table space
32 needed for the fixmap area with a proper one, allowing kernels configured for
33 large CPU counts to actually boot.
34
35 Signed-off-by: Jan Beulich <jbeulich@novell.com>
36
37 ---
38 arch/x86/mm/init_32.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
39 arch/x86/mm/ioremap.c | 25 -------------------------
40 include/asm-x86/io.h | 2 --
41 3 files changed, 46 insertions(+), 30 deletions(-)
42
43 --- a/arch/x86/mm/init_32.c
44 +++ b/arch/x86/mm/init_32.c
45 @@ -137,6 +137,48 @@ static pte_t * __init one_page_table_ini
46 return pte_offset_kernel(pmd, 0);
47 }
48
49 +static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
50 + unsigned long vaddr, pte_t *lastpte)
51 +{
52 +#ifdef CONFIG_HIGHMEM
53 + /*
54 + * Something (early fixmap) may already have put a pte
55 + * page here, which causes the page table allocation
56 + * to become nonlinear. Attempt to fix it, and if it
57 + * is still nonlinear then we have to bug.
58 + */
59 + int pmd_idx_kmap_begin = fix_to_virt(FIX_KMAP_END) >> PMD_SHIFT;
60 + int pmd_idx_kmap_end = fix_to_virt(FIX_KMAP_BEGIN) >> PMD_SHIFT;
61 +
62 + if (pmd_idx_kmap_begin != pmd_idx_kmap_end
63 + && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
64 + && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
65 + && ((__pa(pte) >> PAGE_SHIFT) < table_start
66 + || (__pa(pte) >> PAGE_SHIFT) >= table_end)) {
67 + pte_t *newpte;
68 + unsigned long phys;
69 + int i;
70 +
71 + BUG_ON(after_init_bootmem);
72 + newpte = alloc_low_page(&phys);
73 + for (i = 0; i < PTRS_PER_PTE; i++)
74 + set_pte(newpte + i, pte[i]);
75 +
76 + paravirt_alloc_pte(&init_mm, __pa(newpte) >> PAGE_SHIFT);
77 + set_pmd(pmd, __pmd(__pa(newpte)|_PAGE_TABLE));
78 + BUG_ON(newpte != pte_offset_kernel(pmd, 0));
79 + __flush_tlb_all();
80 +
81 + paravirt_release_pte(__pa(pte) >> PAGE_SHIFT);
82 + pte = newpte;
83 + }
84 + BUG_ON(vaddr < fix_to_virt(FIX_KMAP_BEGIN - 1)
85 + && vaddr > fix_to_virt(FIX_KMAP_END)
86 + && lastpte && lastpte + PTRS_PER_PTE != pte);
87 +#endif
88 + return pte;
89 +}
90 +
91 /*
92 * This function initializes a certain range of kernel virtual memory
93 * with new bootmem page tables, everywhere page tables are missing in
94 @@ -153,6 +195,7 @@ page_table_range_init(unsigned long star
95 unsigned long vaddr;
96 pgd_t *pgd;
97 pmd_t *pmd;
98 + pte_t *pte = NULL;
99
100 vaddr = start;
101 pgd_idx = pgd_index(vaddr);
102 @@ -164,7 +207,8 @@ page_table_range_init(unsigned long star
103 pmd = pmd + pmd_index(vaddr);
104 for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
105 pmd++, pmd_idx++) {
106 - one_page_table_init(pmd);
107 + pte = page_table_kmap_check(one_page_table_init(pmd),
108 + pmd, vaddr, pte);
109
110 vaddr += PMD_SIZE;
111 }
112 @@ -447,7 +491,6 @@ static void __init early_ioremap_page_ta
113 * Fixed mappings, only the page table structure has to be
114 * created - mappings will be set by set_fixmap():
115 */
116 - early_ioremap_clear();
117 vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
118 end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
119 page_table_range_init(vaddr, end, pgd_base);
120 @@ -740,7 +783,7 @@ static void __init find_early_table_spac
121 tables += PAGE_ALIGN(ptes * sizeof(pte_t));
122
123 /* for fixmap */
124 - tables += PAGE_SIZE * 2;
125 + tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t));
126
127 /*
128 * RED-PEN putting page tables only on node 0 could
129 --- a/arch/x86/mm/ioremap.c
130 +++ b/arch/x86/mm/ioremap.c
131 @@ -480,34 +480,9 @@ void __init early_ioremap_init(void)
132 }
133 }
134
135 -void __init early_ioremap_clear(void)
136 -{
137 - pmd_t *pmd;
138 -
139 - if (early_ioremap_debug)
140 - printk(KERN_INFO "early_ioremap_clear()\n");
141 -
142 - pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
143 - pmd_clear(pmd);
144 - paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
145 - __flush_tlb_all();
146 -}
147 -
148 void __init early_ioremap_reset(void)
149 {
150 - enum fixed_addresses idx;
151 - unsigned long addr, phys;
152 - pte_t *pte;
153 -
154 after_paging_init = 1;
155 - for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
156 - addr = fix_to_virt(idx);
157 - pte = early_ioremap_pte(addr);
158 - if (pte_present(*pte)) {
159 - phys = pte_val(*pte) & PAGE_MASK;
160 - set_fixmap(idx, phys);
161 - }
162 - }
163 }
164
165 static void __init __early_set_fixmap(enum fixed_addresses idx,
166 --- a/include/asm-x86/io.h
167 +++ b/include/asm-x86/io.h
168 @@ -12,7 +12,6 @@
169 */
170 #ifndef __ASSEMBLY__
171 extern void early_ioremap_init(void);
172 -extern void early_ioremap_clear(void);
173 extern void early_ioremap_reset(void);
174 extern void *early_ioremap(unsigned long offset, unsigned long size);
175 extern void early_iounmap(void *addr, unsigned long size);
176 @@ -92,7 +91,6 @@ extern void __iomem *ioremap_wc(unsigned
177 * A boot-time mapping is currently limited to at most 16 pages.
178 */
179 extern void early_ioremap_init(void);
180 -extern void early_ioremap_clear(void);
181 extern void early_ioremap_reset(void);
182 extern void *early_ioremap(unsigned long offset, unsigned long size);
183 extern void early_iounmap(void *addr, unsigned long size);