diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-09-23 17:08:43 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-09-23 17:08:43 -0400 |
commit | d7a4b414eed51f1653bb05ebe84122bf9a7ae18b (patch) | |
tree | bd6603a0c27de4c138a1767871897e9cd3e1a1d2 /arch/x86/mm/fault.c | |
parent | 1f0ab40976460bc4673fa204ce917a725185d8f2 (diff) | |
parent | a724eada8c2a7b62463b73ccf73fd0bb6e928aeb (diff) |
Merge commit 'linus/master' into tracing/kprobes
Conflicts:
kernel/trace/Makefile
kernel/trace/trace.h
kernel/trace/trace_event_types.h
kernel/trace/trace_export.c
Merge reason:
Sync with latest significant tracing core changes.
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r-- | arch/x86/mm/fault.c | 59 |
1 files changed, 25 insertions, 34 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index c322e59f2d10..923ea3fb7037 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/bootmem.h> /* max_low_pfn */ | 10 | #include <linux/bootmem.h> /* max_low_pfn */ |
11 | #include <linux/kprobes.h> /* __kprobes, ... */ | 11 | #include <linux/kprobes.h> /* __kprobes, ... */ |
12 | #include <linux/mmiotrace.h> /* kmmio_handler, ... */ | 12 | #include <linux/mmiotrace.h> /* kmmio_handler, ... */ |
13 | #include <linux/perf_counter.h> /* perf_swcounter_event */ | 13 | #include <linux/perf_event.h> /* perf_sw_event */ |
14 | 14 | ||
15 | #include <asm/traps.h> /* dotraplinkage, ... */ | 15 | #include <asm/traps.h> /* dotraplinkage, ... */ |
16 | #include <asm/pgalloc.h> /* pgd_*(), ... */ | 16 | #include <asm/pgalloc.h> /* pgd_*(), ... */ |
@@ -286,26 +286,25 @@ check_v8086_mode(struct pt_regs *regs, unsigned long address, | |||
286 | tsk->thread.screen_bitmap |= 1 << bit; | 286 | tsk->thread.screen_bitmap |= 1 << bit; |
287 | } | 287 | } |
288 | 288 | ||
289 | static void dump_pagetable(unsigned long address) | 289 | static bool low_pfn(unsigned long pfn) |
290 | { | 290 | { |
291 | __typeof__(pte_val(__pte(0))) page; | 291 | return pfn < max_low_pfn; |
292 | } | ||
292 | 293 | ||
293 | page = read_cr3(); | 294 | static void dump_pagetable(unsigned long address) |
294 | page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT]; | 295 | { |
296 | pgd_t *base = __va(read_cr3()); | ||
297 | pgd_t *pgd = &base[pgd_index(address)]; | ||
298 | pmd_t *pmd; | ||
299 | pte_t *pte; | ||
295 | 300 | ||
296 | #ifdef CONFIG_X86_PAE | 301 | #ifdef CONFIG_X86_PAE |
297 | printk("*pdpt = %016Lx ", page); | 302 | printk("*pdpt = %016Lx ", pgd_val(*pgd)); |
298 | if ((page >> PAGE_SHIFT) < max_low_pfn | 303 | if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd)) |
299 | && page & _PAGE_PRESENT) { | 304 | goto out; |
300 | page &= PAGE_MASK; | ||
301 | page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT) | ||
302 | & (PTRS_PER_PMD - 1)]; | ||
303 | printk(KERN_CONT "*pde = %016Lx ", page); | ||
304 | page &= ~_PAGE_NX; | ||
305 | } | ||
306 | #else | ||
307 | printk("*pde = %08lx ", page); | ||
308 | #endif | 305 | #endif |
306 | pmd = pmd_offset(pud_offset(pgd, address), address); | ||
307 | printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd)); | ||
309 | 308 | ||
310 | /* | 309 | /* |
311 | * We must not directly access the pte in the highpte | 310 | * We must not directly access the pte in the highpte |
@@ -313,16 +312,12 @@ static void dump_pagetable(unsigned long address) | |||
313 | * And let's rather not kmap-atomic the pte, just in case | 312 | * And let's rather not kmap-atomic the pte, just in case |
314 | * it's allocated already: | 313 | * it's allocated already: |
315 | */ | 314 | */ |
316 | if ((page >> PAGE_SHIFT) < max_low_pfn | 315 | if (!low_pfn(pmd_pfn(*pmd)) || !pmd_present(*pmd) || pmd_large(*pmd)) |
317 | && (page & _PAGE_PRESENT) | 316 | goto out; |
318 | && !(page & _PAGE_PSE)) { | ||
319 | |||
320 | page &= PAGE_MASK; | ||
321 | page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT) | ||
322 | & (PTRS_PER_PTE - 1)]; | ||
323 | printk("*pte = %0*Lx ", sizeof(page)*2, (u64)page); | ||
324 | } | ||
325 | 317 | ||
318 | pte = pte_offset_kernel(pmd, address); | ||
319 | printk("*pte = %0*Lx ", sizeof(*pte) * 2, (u64)pte_val(*pte)); | ||
320 | out: | ||
326 | printk("\n"); | 321 | printk("\n"); |
327 | } | 322 | } |
328 | 323 | ||
@@ -451,16 +446,12 @@ static int bad_address(void *p) | |||
451 | 446 | ||
452 | static void dump_pagetable(unsigned long address) | 447 | static void dump_pagetable(unsigned long address) |
453 | { | 448 | { |
454 | pgd_t *pgd; | 449 | pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK); |
450 | pgd_t *pgd = base + pgd_index(address); | ||
455 | pud_t *pud; | 451 | pud_t *pud; |
456 | pmd_t *pmd; | 452 | pmd_t *pmd; |
457 | pte_t *pte; | 453 | pte_t *pte; |
458 | 454 | ||
459 | pgd = (pgd_t *)read_cr3(); | ||
460 | |||
461 | pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); | ||
462 | |||
463 | pgd += pgd_index(address); | ||
464 | if (bad_address(pgd)) | 455 | if (bad_address(pgd)) |
465 | goto bad; | 456 | goto bad; |
466 | 457 | ||
@@ -1027,7 +1018,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1027 | if (unlikely(error_code & PF_RSVD)) | 1018 | if (unlikely(error_code & PF_RSVD)) |
1028 | pgtable_bad(regs, error_code, address); | 1019 | pgtable_bad(regs, error_code, address); |
1029 | 1020 | ||
1030 | perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); | 1021 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); |
1031 | 1022 | ||
1032 | /* | 1023 | /* |
1033 | * If we're in an interrupt, have no user context or are running | 1024 | * If we're in an interrupt, have no user context or are running |
@@ -1124,11 +1115,11 @@ good_area: | |||
1124 | 1115 | ||
1125 | if (fault & VM_FAULT_MAJOR) { | 1116 | if (fault & VM_FAULT_MAJOR) { |
1126 | tsk->maj_flt++; | 1117 | tsk->maj_flt++; |
1127 | perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, | 1118 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, |
1128 | regs, address); | 1119 | regs, address); |
1129 | } else { | 1120 | } else { |
1130 | tsk->min_flt++; | 1121 | tsk->min_flt++; |
1131 | perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | 1122 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, |
1132 | regs, address); | 1123 | regs, address); |
1133 | } | 1124 | } |
1134 | 1125 | ||