aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/fault.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-20 16:50:24 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-20 18:09:43 -0500
commitf2f13a8535174dbb813a0607a9d4737cfba98f6c (patch)
treea7e2d70cef8dbc6fc5ac2e878e1fc7435a6f6203 /arch/x86/mm/fault.c
parentb18018126f422f5b706fd750373425e10e84b486 (diff)
x86, mm: fault.c, reorder functions
Impact: cleanup Avoid a couple more #ifdefs by moving fundamentally non-unifiable functions into a single #ifdef 32-bit / #else / #endif block in fault.c: vmalloc*(), dump_pagetable(), check_vm8086_mode(). No code changed: text data bss dec hex filename 4618 32 24 4674 1242 fault.o.before 4618 32 24 4674 1242 fault.o.after Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r--arch/x86/mm/fault.c474
1 files changed, 239 insertions, 235 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 379beaec6caa..4ce62fb80da7 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -191,18 +191,124 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,
191 force_sig_info(si_signo, &info, tsk); 191 force_sig_info(si_signo, &info, tsk);
192} 192}
193 193
194#ifdef CONFIG_X86_64 194DEFINE_SPINLOCK(pgd_lock);
195static int bad_address(void *p) 195LIST_HEAD(pgd_list);
196
197#ifdef CONFIG_X86_32
198static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
196{ 199{
197 unsigned long dummy; 200 unsigned index = pgd_index(address);
201 pgd_t *pgd_k;
202 pud_t *pud, *pud_k;
203 pmd_t *pmd, *pmd_k;
198 204
199 return probe_kernel_address((unsigned long *)p, dummy); 205 pgd += index;
206 pgd_k = init_mm.pgd + index;
207
208 if (!pgd_present(*pgd_k))
209 return NULL;
210
211 /*
212 * set_pgd(pgd, *pgd_k); here would be useless on PAE
213 * and redundant with the set_pmd() on non-PAE. As would
214 * set_pud.
215 */
216 pud = pud_offset(pgd, address);
217 pud_k = pud_offset(pgd_k, address);
218 if (!pud_present(*pud_k))
219 return NULL;
220
221 pmd = pmd_offset(pud, address);
222 pmd_k = pmd_offset(pud_k, address);
223 if (!pmd_present(*pmd_k))
224 return NULL;
225
226 if (!pmd_present(*pmd)) {
227 set_pmd(pmd, *pmd_k);
228 arch_flush_lazy_mmu_mode();
229 } else {
230 BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
231 }
232
233 return pmd_k;
234}
235
236void vmalloc_sync_all(void)
237{
238 unsigned long address;
239
240 if (SHARED_KERNEL_PMD)
241 return;
242
243 for (address = VMALLOC_START & PMD_MASK;
244 address >= TASK_SIZE && address < FIXADDR_TOP;
245 address += PMD_SIZE) {
246
247 unsigned long flags;
248 struct page *page;
249
250 spin_lock_irqsave(&pgd_lock, flags);
251 list_for_each_entry(page, &pgd_list, lru) {
252 if (!vmalloc_sync_one(page_address(page), address))
253 break;
254 }
255 spin_unlock_irqrestore(&pgd_lock, flags);
256 }
257}
258
259/*
260 * 32-bit:
261 *
262 * Handle a fault on the vmalloc or module mapping area
263 */
264static noinline int vmalloc_fault(unsigned long address)
265{
266 unsigned long pgd_paddr;
267 pmd_t *pmd_k;
268 pte_t *pte_k;
269
270 /* Make sure we are in vmalloc area: */
271 if (!(address >= VMALLOC_START && address < VMALLOC_END))
272 return -1;
273
274 /*
275 * Synchronize this task's top level page-table
276 * with the 'reference' page table.
277 *
278 * Do _not_ use "current" here. We might be inside
279 * an interrupt in the middle of a task switch..
280 */
281 pgd_paddr = read_cr3();
282 pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
283 if (!pmd_k)
284 return -1;
285
286 pte_k = pte_offset_kernel(pmd_k, address);
287 if (!pte_present(*pte_k))
288 return -1;
289
290 return 0;
291}
292
293/*
294 * Did it hit the DOS screen memory VA from vm86 mode?
295 */
296static inline void
297check_v8086_mode(struct pt_regs *regs, unsigned long address,
298 struct task_struct *tsk)
299{
300 unsigned long bit;
301
302 if (!v8086_mode(regs))
303 return;
304
305 bit = (address - 0xA0000) >> PAGE_SHIFT;
306 if (bit < 32)
307 tsk->thread.screen_bitmap |= 1 << bit;
200} 308}
201#endif
202 309
203static void dump_pagetable(unsigned long address) 310static void dump_pagetable(unsigned long address)
204{ 311{
205#ifdef CONFIG_X86_32
206 __typeof__(pte_val(__pte(0))) page; 312 __typeof__(pte_val(__pte(0))) page;
207 313
208 page = read_cr3(); 314 page = read_cr3();
@@ -239,7 +345,132 @@ static void dump_pagetable(unsigned long address)
239 } 345 }
240 346
241 printk("\n"); 347 printk("\n");
242#else /* CONFIG_X86_64 */ 348}
349
350#else /* CONFIG_X86_64: */
351
352void vmalloc_sync_all(void)
353{
354 unsigned long address;
355
356 for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
357 address += PGDIR_SIZE) {
358
359 const pgd_t *pgd_ref = pgd_offset_k(address);
360 unsigned long flags;
361 struct page *page;
362
363 if (pgd_none(*pgd_ref))
364 continue;
365
366 spin_lock_irqsave(&pgd_lock, flags);
367 list_for_each_entry(page, &pgd_list, lru) {
368 pgd_t *pgd;
369 pgd = (pgd_t *)page_address(page) + pgd_index(address);
370 if (pgd_none(*pgd))
371 set_pgd(pgd, *pgd_ref);
372 else
373 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
374 }
375 spin_unlock_irqrestore(&pgd_lock, flags);
376 }
377}
378
379/*
380 * 64-bit:
381 *
382 * Handle a fault on the vmalloc area
383 *
384 * This assumes no large pages in there.
385 */
386static noinline int vmalloc_fault(unsigned long address)
387{
388 pgd_t *pgd, *pgd_ref;
389 pud_t *pud, *pud_ref;
390 pmd_t *pmd, *pmd_ref;
391 pte_t *pte, *pte_ref;
392
393 /* Make sure we are in vmalloc area: */
394 if (!(address >= VMALLOC_START && address < VMALLOC_END))
395 return -1;
396
397 /*
398 * Copy kernel mappings over when needed. This can also
399 * happen within a race in page table update. In the later
400 * case just flush:
401 */
402 pgd = pgd_offset(current->active_mm, address);
403 pgd_ref = pgd_offset_k(address);
404 if (pgd_none(*pgd_ref))
405 return -1;
406
407 if (pgd_none(*pgd))
408 set_pgd(pgd, *pgd_ref);
409 else
410 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
411
412 /*
413 * Below here mismatches are bugs because these lower tables
414 * are shared:
415 */
416
417 pud = pud_offset(pgd, address);
418 pud_ref = pud_offset(pgd_ref, address);
419 if (pud_none(*pud_ref))
420 return -1;
421
422 if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
423 BUG();
424
425 pmd = pmd_offset(pud, address);
426 pmd_ref = pmd_offset(pud_ref, address);
427 if (pmd_none(*pmd_ref))
428 return -1;
429
430 if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
431 BUG();
432
433 pte_ref = pte_offset_kernel(pmd_ref, address);
434 if (!pte_present(*pte_ref))
435 return -1;
436
437 pte = pte_offset_kernel(pmd, address);
438
439 /*
440 * Don't use pte_page here, because the mappings can point
441 * outside mem_map, and the NUMA hash lookup cannot handle
442 * that:
443 */
444 if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
445 BUG();
446
447 return 0;
448}
449
450static const char errata93_warning[] =
451KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
452KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
453KERN_ERR "******* Please consider a BIOS update.\n"
454KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
455
456/*
457 * No vm86 mode in 64-bit mode:
458 */
459static inline void
460check_v8086_mode(struct pt_regs *regs, unsigned long address,
461 struct task_struct *tsk)
462{
463}
464
465static int bad_address(void *p)
466{
467 unsigned long dummy;
468
469 return probe_kernel_address((unsigned long *)p, dummy);
470}
471
472static void dump_pagetable(unsigned long address)
473{
243 pgd_t *pgd; 474 pgd_t *pgd;
244 pud_t *pud; 475 pud_t *pud;
245 pmd_t *pmd; 476 pmd_t *pmd;
@@ -284,83 +515,9 @@ out:
284 return; 515 return;
285bad: 516bad:
286 printk("BAD\n"); 517 printk("BAD\n");
287#endif
288}
289
290#ifdef CONFIG_X86_32
291static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
292{
293 unsigned index = pgd_index(address);
294 pgd_t *pgd_k;
295 pud_t *pud, *pud_k;
296 pmd_t *pmd, *pmd_k;
297
298 pgd += index;
299 pgd_k = init_mm.pgd + index;
300
301 if (!pgd_present(*pgd_k))
302 return NULL;
303
304 /*
305 * set_pgd(pgd, *pgd_k); here would be useless on PAE
306 * and redundant with the set_pmd() on non-PAE. As would
307 * set_pud.
308 */
309 pud = pud_offset(pgd, address);
310 pud_k = pud_offset(pgd_k, address);
311 if (!pud_present(*pud_k))
312 return NULL;
313
314 pmd = pmd_offset(pud, address);
315 pmd_k = pmd_offset(pud_k, address);
316 if (!pmd_present(*pmd_k))
317 return NULL;
318
319 if (!pmd_present(*pmd)) {
320 set_pmd(pmd, *pmd_k);
321 arch_flush_lazy_mmu_mode();
322 } else {
323 BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
324 }
325
326 return pmd_k;
327}
328
329/*
330 * Did it hit the DOS screen memory VA from vm86 mode?
331 */
332static inline void
333check_v8086_mode(struct pt_regs *regs, unsigned long address,
334 struct task_struct *tsk)
335{
336 unsigned long bit;
337
338 if (!v8086_mode(regs))
339 return;
340
341 bit = (address - 0xA0000) >> PAGE_SHIFT;
342 if (bit < 32)
343 tsk->thread.screen_bitmap |= 1 << bit;
344}
345
346#else /* CONFIG_X86_64: */
347
348static const char errata93_warning[] =
349KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
350KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
351KERN_ERR "******* Please consider a BIOS update.\n"
352KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
353
354/*
355 * No vm86 mode in 64-bit mode:
356 */
357static inline void
358check_v8086_mode(struct pt_regs *regs, unsigned long address,
359 struct task_struct *tsk)
360{
361} 518}
362 519
363#endif 520#endif /* CONFIG_X86_64 */
364 521
365/* 522/*
366 * Workaround for K8 erratum #93 & buggy BIOS. 523 * Workaround for K8 erratum #93 & buggy BIOS.
@@ -795,109 +952,6 @@ spurious_fault(unsigned long error_code, unsigned long address)
795 return ret; 952 return ret;
796} 953}
797 954
798/*
799 * 32-bit:
800 *
801 * Handle a fault on the vmalloc or module mapping area
802 *
803 * 64-bit:
804 *
805 * Handle a fault on the vmalloc area
806 *
807 * This assumes no large pages in there.
808 */
809static noinline int vmalloc_fault(unsigned long address)
810{
811#ifdef CONFIG_X86_32
812 unsigned long pgd_paddr;
813 pmd_t *pmd_k;
814 pte_t *pte_k;
815
816 /* Make sure we are in vmalloc area: */
817 if (!(address >= VMALLOC_START && address < VMALLOC_END))
818 return -1;
819
820 /*
821 * Synchronize this task's top level page-table
822 * with the 'reference' page table.
823 *
824 * Do _not_ use "current" here. We might be inside
825 * an interrupt in the middle of a task switch..
826 */
827 pgd_paddr = read_cr3();
828 pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
829 if (!pmd_k)
830 return -1;
831
832 pte_k = pte_offset_kernel(pmd_k, address);
833 if (!pte_present(*pte_k))
834 return -1;
835
836 return 0;
837#else
838 pgd_t *pgd, *pgd_ref;
839 pud_t *pud, *pud_ref;
840 pmd_t *pmd, *pmd_ref;
841 pte_t *pte, *pte_ref;
842
843 /* Make sure we are in vmalloc area: */
844 if (!(address >= VMALLOC_START && address < VMALLOC_END))
845 return -1;
846
847 /*
848 * Copy kernel mappings over when needed. This can also
849 * happen within a race in page table update. In the later
850 * case just flush:
851 */
852 pgd = pgd_offset(current->active_mm, address);
853 pgd_ref = pgd_offset_k(address);
854 if (pgd_none(*pgd_ref))
855 return -1;
856
857 if (pgd_none(*pgd))
858 set_pgd(pgd, *pgd_ref);
859 else
860 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
861
862 /*
863 * Below here mismatches are bugs because these lower tables
864 * are shared:
865 */
866
867 pud = pud_offset(pgd, address);
868 pud_ref = pud_offset(pgd_ref, address);
869 if (pud_none(*pud_ref))
870 return -1;
871
872 if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
873 BUG();
874
875 pmd = pmd_offset(pud, address);
876 pmd_ref = pmd_offset(pud_ref, address);
877 if (pmd_none(*pmd_ref))
878 return -1;
879
880 if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
881 BUG();
882
883 pte_ref = pte_offset_kernel(pmd_ref, address);
884 if (!pte_present(*pte_ref))
885 return -1;
886
887 pte = pte_offset_kernel(pmd, address);
888
889 /*
890 * Don't use pte_page here, because the mappings can point
891 * outside mem_map, and the NUMA hash lookup cannot handle
892 * that:
893 */
894 if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
895 BUG();
896
897 return 0;
898#endif
899}
900
901int show_unhandled_signals = 1; 955int show_unhandled_signals = 1;
902 956
903static inline int 957static inline int
@@ -1115,53 +1169,3 @@ good_area:
1115 1169
1116 up_read(&mm->mmap_sem); 1170 up_read(&mm->mmap_sem);
1117} 1171}
1118
1119DEFINE_SPINLOCK(pgd_lock);
1120LIST_HEAD(pgd_list);
1121
1122void vmalloc_sync_all(void)
1123{
1124 unsigned long address;
1125
1126#ifdef CONFIG_X86_32
1127 if (SHARED_KERNEL_PMD)
1128 return;
1129
1130 for (address = VMALLOC_START & PMD_MASK;
1131 address >= TASK_SIZE && address < FIXADDR_TOP;
1132 address += PMD_SIZE) {
1133
1134 unsigned long flags;
1135 struct page *page;
1136
1137 spin_lock_irqsave(&pgd_lock, flags);
1138 list_for_each_entry(page, &pgd_list, lru) {
1139 if (!vmalloc_sync_one(page_address(page), address))
1140 break;
1141 }
1142 spin_unlock_irqrestore(&pgd_lock, flags);
1143 }
1144#else /* CONFIG_X86_64 */
1145 for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
1146 address += PGDIR_SIZE) {
1147
1148 const pgd_t *pgd_ref = pgd_offset_k(address);
1149 unsigned long flags;
1150 struct page *page;
1151
1152 if (pgd_none(*pgd_ref))
1153 continue;
1154
1155 spin_lock_irqsave(&pgd_lock, flags);
1156 list_for_each_entry(page, &pgd_list, lru) {
1157 pgd_t *pgd;
1158 pgd = (pgd_t *)page_address(page) + pgd_index(address);
1159 if (pgd_none(*pgd))
1160 set_pgd(pgd, *pgd_ref);
1161 else
1162 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
1163 }
1164 spin_unlock_irqrestore(&pgd_lock, flags);
1165 }
1166#endif
1167}