diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/pgtable.h | 10 | ||||
-rw-r--r-- | arch/x86/mm/fault.c | 51 |
2 files changed, 26 insertions, 35 deletions
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 3cc06e3fceb8..af5481e94863 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
@@ -134,6 +134,11 @@ static inline unsigned long pte_pfn(pte_t pte) | |||
134 | return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; | 134 | return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; |
135 | } | 135 | } |
136 | 136 | ||
137 | static inline unsigned long pmd_pfn(pmd_t pmd) | ||
138 | { | ||
139 | return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; | ||
140 | } | ||
141 | |||
137 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) | 142 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) |
138 | 143 | ||
139 | static inline int pmd_large(pmd_t pte) | 144 | static inline int pmd_large(pmd_t pte) |
@@ -422,11 +427,6 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) | |||
422 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); | 427 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); |
423 | } | 428 | } |
424 | 429 | ||
425 | static inline unsigned long pmd_pfn(pmd_t pmd) | ||
426 | { | ||
427 | return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; | ||
428 | } | ||
429 | |||
430 | static inline int pud_large(pud_t pud) | 430 | static inline int pud_large(pud_t pud) |
431 | { | 431 | { |
432 | return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == | 432 | return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 78a5fff857be..9bf7e52c2869 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -285,26 +285,25 @@ check_v8086_mode(struct pt_regs *regs, unsigned long address, | |||
285 | tsk->thread.screen_bitmap |= 1 << bit; | 285 | tsk->thread.screen_bitmap |= 1 << bit; |
286 | } | 286 | } |
287 | 287 | ||
288 | static void dump_pagetable(unsigned long address) | 288 | static bool low_pfn(unsigned long pfn) |
289 | { | 289 | { |
290 | __typeof__(pte_val(__pte(0))) page; | 290 | return pfn < max_low_pfn; |
291 | } | ||
291 | 292 | ||
292 | page = read_cr3(); | 293 | static void dump_pagetable(unsigned long address) |
293 | page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT]; | 294 | { |
295 | pgd_t *base = __va(read_cr3()); | ||
296 | pgd_t *pgd = &base[pgd_index(address)]; | ||
297 | pmd_t *pmd; | ||
298 | pte_t *pte; | ||
294 | 299 | ||
295 | #ifdef CONFIG_X86_PAE | 300 | #ifdef CONFIG_X86_PAE |
296 | printk("*pdpt = %016Lx ", page); | 301 | printk("*pdpt = %016Lx ", pgd_val(*pgd)); |
297 | if ((page >> PAGE_SHIFT) < max_low_pfn | 302 | if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd)) |
298 | && page & _PAGE_PRESENT) { | 303 | goto out; |
299 | page &= PAGE_MASK; | ||
300 | page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT) | ||
301 | & (PTRS_PER_PMD - 1)]; | ||
302 | printk(KERN_CONT "*pde = %016Lx ", page); | ||
303 | page &= ~_PAGE_NX; | ||
304 | } | ||
305 | #else | ||
306 | printk("*pde = %08lx ", page); | ||
307 | #endif | 304 | #endif |
305 | pmd = pmd_offset(pud_offset(pgd, address), address); | ||
306 | printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd)); | ||
308 | 307 | ||
309 | /* | 308 | /* |
310 | * We must not directly access the pte in the highpte | 309 | * We must not directly access the pte in the highpte |
@@ -312,16 +311,12 @@ static void dump_pagetable(unsigned long address) | |||
312 | * And let's rather not kmap-atomic the pte, just in case | 311 | * And let's rather not kmap-atomic the pte, just in case |
313 | * it's allocated already: | 312 | * it's allocated already: |
314 | */ | 313 | */ |
315 | if ((page >> PAGE_SHIFT) < max_low_pfn | 314 | if (!low_pfn(pmd_pfn(*pmd)) || !pmd_present(*pmd) || pmd_large(*pmd)) |
316 | && (page & _PAGE_PRESENT) | 315 | goto out; |
317 | && !(page & _PAGE_PSE)) { | ||
318 | |||
319 | page &= PAGE_MASK; | ||
320 | page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT) | ||
321 | & (PTRS_PER_PTE - 1)]; | ||
322 | printk("*pte = %0*Lx ", sizeof(page)*2, (u64)page); | ||
323 | } | ||
324 | 316 | ||
317 | pte = pte_offset_kernel(pmd, address); | ||
318 | printk("*pte = %0*Lx ", sizeof(*pte) * 2, (u64)pte_val(*pte)); | ||
319 | out: | ||
325 | printk("\n"); | 320 | printk("\n"); |
326 | } | 321 | } |
327 | 322 | ||
@@ -449,16 +444,12 @@ static int bad_address(void *p) | |||
449 | 444 | ||
450 | static void dump_pagetable(unsigned long address) | 445 | static void dump_pagetable(unsigned long address) |
451 | { | 446 | { |
452 | pgd_t *pgd; | 447 | pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK); |
448 | pgd_t *pgd = base + pgd_index(address); | ||
453 | pud_t *pud; | 449 | pud_t *pud; |
454 | pmd_t *pmd; | 450 | pmd_t *pmd; |
455 | pte_t *pte; | 451 | pte_t *pte; |
456 | 452 | ||
457 | pgd = (pgd_t *)read_cr3(); | ||
458 | |||
459 | pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); | ||
460 | |||
461 | pgd += pgd_index(address); | ||
462 | if (bad_address(pgd)) | 453 | if (bad_address(pgd)) |
463 | goto bad; | 454 | goto bad; |
464 | 455 | ||