aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorHarvey Harrison <harvey.harrison@gmail.com>2008-01-30 07:33:13 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:13 -0500
commitfdfe8aa84dd78cfdff427d0520f5974fb5e9c220 (patch)
tree0d9ee510fa3bc5652e345bec5fb5ffd66010ca97 /arch/x86/mm
parent6f4d368ef9e9f91aa0019c11e90773ea32d94625 (diff)
x86: function ifdefs in fault_32|64.c
Add caller of is_errata93() to X86_32, ifdef'd to do nothing. Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/fault_32.c59
-rw-r--r--arch/x86/mm/fault_64.c30
2 files changed, 83 insertions, 6 deletions
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index 31113deeb7c0..eba90198b15a 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.c
@@ -217,6 +217,7 @@ KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
217KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n" 217KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
218KERN_ERR "******* Please consider a BIOS update.\n" 218KERN_ERR "******* Please consider a BIOS update.\n"
219KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n"; 219KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
220#endif
220 221
221/* Workaround for K8 erratum #93 & buggy BIOS. 222/* Workaround for K8 erratum #93 & buggy BIOS.
222 BIOS SMM functions are required to use a specific workaround 223 BIOS SMM functions are required to use a specific workaround
@@ -224,10 +225,12 @@ KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
224 A lot of BIOS that didn't get tested properly miss this. 225 A lot of BIOS that didn't get tested properly miss this.
225 The OS sees this as a page fault with the upper 32bits of RIP cleared. 226 The OS sees this as a page fault with the upper 32bits of RIP cleared.
226 Try to work around it here. 227 Try to work around it here.
227 Note we only handle faults in kernel here. */ 228 Note we only handle faults in kernel here.
228 229 Does nothing for X86_32
230 */
229static int is_errata93(struct pt_regs *regs, unsigned long address) 231static int is_errata93(struct pt_regs *regs, unsigned long address)
230{ 232{
233#ifdef CONFIG_X86_64
231 static int warned; 234 static int warned;
232 if (address != regs->ip) 235 if (address != regs->ip)
233 return 0; 236 return 0;
@@ -243,9 +246,10 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
243 regs->ip = address; 246 regs->ip = address;
244 return 1; 247 return 1;
245 } 248 }
249#endif
246 return 0; 250 return 0;
247} 251}
248#endif 252
249 253
250/* 254/*
251 * Handle a fault on the vmalloc or module mapping area 255 * Handle a fault on the vmalloc or module mapping area
@@ -254,6 +258,7 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
254 */ 258 */
255static inline int vmalloc_fault(unsigned long address) 259static inline int vmalloc_fault(unsigned long address)
256{ 260{
261#ifdef CONFIG_X86_32
257 unsigned long pgd_paddr; 262 unsigned long pgd_paddr;
258 pmd_t *pmd_k; 263 pmd_t *pmd_k;
259 pte_t *pte_k; 264 pte_t *pte_k;
@@ -272,6 +277,51 @@ static inline int vmalloc_fault(unsigned long address)
272 if (!pte_present(*pte_k)) 277 if (!pte_present(*pte_k))
273 return -1; 278 return -1;
274 return 0; 279 return 0;
280#else
281 pgd_t *pgd, *pgd_ref;
282 pud_t *pud, *pud_ref;
283 pmd_t *pmd, *pmd_ref;
284 pte_t *pte, *pte_ref;
285
286 /* Copy kernel mappings over when needed. This can also
287 happen within a race in page table update. In the later
288 case just flush. */
289
290 pgd = pgd_offset(current->mm ?: &init_mm, address);
291 pgd_ref = pgd_offset_k(address);
292 if (pgd_none(*pgd_ref))
293 return -1;
294 if (pgd_none(*pgd))
295 set_pgd(pgd, *pgd_ref);
296 else
297 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
298
299 /* Below here mismatches are bugs because these lower tables
300 are shared */
301
302 pud = pud_offset(pgd, address);
303 pud_ref = pud_offset(pgd_ref, address);
304 if (pud_none(*pud_ref))
305 return -1;
306 if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
307 BUG();
308 pmd = pmd_offset(pud, address);
309 pmd_ref = pmd_offset(pud_ref, address);
310 if (pmd_none(*pmd_ref))
311 return -1;
312 if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
313 BUG();
314 pte_ref = pte_offset_kernel(pmd_ref, address);
315 if (!pte_present(*pte_ref))
316 return -1;
317 pte = pte_offset_kernel(pmd, address);
318 /* Don't use pte_page here, because the mappings can point
319 outside mem_map, and the NUMA hash lookup cannot handle
320 that. */
321 if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
322 BUG();
323 return 0;
324#endif
275} 325}
276 326
277int show_unhandled_signals = 1; 327int show_unhandled_signals = 1;
@@ -507,6 +557,9 @@ no_context:
507 if (is_prefetch(regs, address, error_code)) 557 if (is_prefetch(regs, address, error_code))
508 return; 558 return;
509 559
560 if (is_errata93(regs, address))
561 return;
562
510/* 563/*
511 * Oops. The kernel tried to access some bad page. We'll have to 564 * Oops. The kernel tried to access some bad page. We'll have to
512 * terminate things with extreme prejudice. 565 * terminate things with extreme prejudice.
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c
index c48d95c306df..75b7b165bdf3 100644
--- a/arch/x86/mm/fault_64.c
+++ b/arch/x86/mm/fault_64.c
@@ -223,6 +223,7 @@ KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
223KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n" 223KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
224KERN_ERR "******* Please consider a BIOS update.\n" 224KERN_ERR "******* Please consider a BIOS update.\n"
225KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n"; 225KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
226#endif
226 227
227/* Workaround for K8 erratum #93 & buggy BIOS. 228/* Workaround for K8 erratum #93 & buggy BIOS.
228 BIOS SMM functions are required to use a specific workaround 229 BIOS SMM functions are required to use a specific workaround
@@ -230,10 +231,12 @@ KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
230 A lot of BIOS that didn't get tested properly miss this. 231 A lot of BIOS that didn't get tested properly miss this.
231 The OS sees this as a page fault with the upper 32bits of RIP cleared. 232 The OS sees this as a page fault with the upper 32bits of RIP cleared.
232 Try to work around it here. 233 Try to work around it here.
233 Note we only handle faults in kernel here. */ 234 Note we only handle faults in kernel here.
234 235 Does nothing for X86_32
236 */
235static int is_errata93(struct pt_regs *regs, unsigned long address) 237static int is_errata93(struct pt_regs *regs, unsigned long address)
236{ 238{
239#ifdef CONFIG_X86_64
237 static int warned; 240 static int warned;
238 if (address != regs->ip) 241 if (address != regs->ip)
239 return 0; 242 return 0;
@@ -249,9 +252,9 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
249 regs->ip = address; 252 regs->ip = address;
250 return 1; 253 return 1;
251 } 254 }
255#endif
252 return 0; 256 return 0;
253} 257}
254#endif
255 258
256static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, 259static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
257 unsigned long error_code) 260 unsigned long error_code)
@@ -278,6 +281,26 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
278 */ 281 */
279static int vmalloc_fault(unsigned long address) 282static int vmalloc_fault(unsigned long address)
280{ 283{
284#ifdef CONFIG_X86_32
285 unsigned long pgd_paddr;
286 pmd_t *pmd_k;
287 pte_t *pte_k;
288 /*
289 * Synchronize this task's top level page-table
290 * with the 'reference' page table.
291 *
292 * Do _not_ use "current" here. We might be inside
293 * an interrupt in the middle of a task switch..
294 */
295 pgd_paddr = read_cr3();
296 pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
297 if (!pmd_k)
298 return -1;
299 pte_k = pte_offset_kernel(pmd_k, address);
300 if (!pte_present(*pte_k))
301 return -1;
302 return 0;
303#else
281 pgd_t *pgd, *pgd_ref; 304 pgd_t *pgd, *pgd_ref;
282 pud_t *pud, *pud_ref; 305 pud_t *pud, *pud_ref;
283 pmd_t *pmd, *pmd_ref; 306 pmd_t *pmd, *pmd_ref;
@@ -321,6 +344,7 @@ static int vmalloc_fault(unsigned long address)
321 if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref)) 344 if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
322 BUG(); 345 BUG();
323 return 0; 346 return 0;
347#endif
324} 348}
325 349
326int show_unhandled_signals = 1; 350int show_unhandled_signals = 1;