diff options
author | Harvey Harrison <harvey.harrison@gmail.com> | 2008-01-30 07:34:10 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:34:10 -0500 |
commit | 1156e098c5fc142ceaf091f0627109225a9db894 (patch) | |
tree | 8b338373eecb8ef085e110c3f2dfc6065b7396bd /arch/x86/mm/fault_32.c | |
parent | d7d119d777d7ed22c4095915e9c985a8b75bfe5f (diff) |
x86: unify fault_32|64.c by ifdef'd function bodies
It's about time to get on with unifying these files, elimination
of the ugly ifdefs can occur in the unified file.
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/fault_32.c')
-rw-r--r-- | arch/x86/mm/fault_32.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index 28ea3d3ec8f8..7d9ecbbba745 100644 --- a/arch/x86/mm/fault_32.c +++ b/arch/x86/mm/fault_32.c | |||
@@ -173,8 +173,17 @@ static void force_sig_info_fault(int si_signo, int si_code, | |||
173 | force_sig_info(si_signo, &info, tsk); | 173 | force_sig_info(si_signo, &info, tsk); |
174 | } | 174 | } |
175 | 175 | ||
176 | #ifdef CONFIG_X86_64 | ||
177 | static int bad_address(void *p) | ||
178 | { | ||
179 | unsigned long dummy; | ||
180 | return probe_kernel_address((unsigned long *)p, dummy); | ||
181 | } | ||
182 | #endif | ||
183 | |||
176 | void dump_pagetable(unsigned long address) | 184 | void dump_pagetable(unsigned long address) |
177 | { | 185 | { |
186 | #ifdef CONFIG_X86_32 | ||
178 | __typeof__(pte_val(__pte(0))) page; | 187 | __typeof__(pte_val(__pte(0))) page; |
179 | 188 | ||
180 | page = read_cr3(); | 189 | page = read_cr3(); |
@@ -209,8 +218,42 @@ void dump_pagetable(unsigned long address) | |||
209 | } | 218 | } |
210 | 219 | ||
211 | printk("\n"); | 220 | printk("\n"); |
221 | #else /* CONFIG_X86_64 */ | ||
222 | pgd_t *pgd; | ||
223 | pud_t *pud; | ||
224 | pmd_t *pmd; | ||
225 | pte_t *pte; | ||
226 | |||
227 | pgd = (pgd_t *)read_cr3(); | ||
228 | |||
229 | pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); | ||
230 | pgd += pgd_index(address); | ||
231 | if (bad_address(pgd)) goto bad; | ||
232 | printk("PGD %lx ", pgd_val(*pgd)); | ||
233 | if (!pgd_present(*pgd)) goto ret; | ||
234 | |||
235 | pud = pud_offset(pgd, address); | ||
236 | if (bad_address(pud)) goto bad; | ||
237 | printk("PUD %lx ", pud_val(*pud)); | ||
238 | if (!pud_present(*pud)) goto ret; | ||
239 | |||
240 | pmd = pmd_offset(pud, address); | ||
241 | if (bad_address(pmd)) goto bad; | ||
242 | printk("PMD %lx ", pmd_val(*pmd)); | ||
243 | if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret; | ||
244 | |||
245 | pte = pte_offset_kernel(pmd, address); | ||
246 | if (bad_address(pte)) goto bad; | ||
247 | printk("PTE %lx", pte_val(*pte)); | ||
248 | ret: | ||
249 | printk("\n"); | ||
250 | return; | ||
251 | bad: | ||
252 | printk("BAD\n"); | ||
253 | #endif | ||
212 | } | 254 | } |
213 | 255 | ||
256 | #ifdef CONFIG_X86_32 | ||
214 | static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) | 257 | static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) |
215 | { | 258 | { |
216 | unsigned index = pgd_index(address); | 259 | unsigned index = pgd_index(address); |
@@ -246,6 +289,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) | |||
246 | BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); | 289 | BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); |
247 | return pmd_k; | 290 | return pmd_k; |
248 | } | 291 | } |
292 | #endif | ||
249 | 293 | ||
250 | #ifdef CONFIG_X86_64 | 294 | #ifdef CONFIG_X86_64 |
251 | static const char errata93_warning[] = | 295 | static const char errata93_warning[] = |
@@ -326,6 +370,7 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address) | |||
326 | static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, | 370 | static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, |
327 | unsigned long address) | 371 | unsigned long address) |
328 | { | 372 | { |
373 | #ifdef CONFIG_X86_32 | ||
329 | if (!oops_may_print()) | 374 | if (!oops_may_print()) |
330 | return; | 375 | return; |
331 | 376 | ||
@@ -350,8 +395,40 @@ static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, | |||
350 | printk(KERN_ALERT "IP:"); | 395 | printk(KERN_ALERT "IP:"); |
351 | printk_address(regs->ip, 1); | 396 | printk_address(regs->ip, 1); |
352 | dump_pagetable(address); | 397 | dump_pagetable(address); |
398 | #else /* CONFIG_X86_64 */ | ||
399 | printk(KERN_ALERT "BUG: unable to handle kernel "); | ||
400 | if (address < PAGE_SIZE) | ||
401 | printk(KERN_CONT "NULL pointer dereference"); | ||
402 | else | ||
403 | printk(KERN_CONT "paging request"); | ||
404 | printk(KERN_CONT " at %016lx\n", address); | ||
405 | |||
406 | printk(KERN_ALERT "IP:"); | ||
407 | printk_address(regs->ip, 1); | ||
408 | dump_pagetable(address); | ||
409 | #endif | ||
353 | } | 410 | } |
354 | 411 | ||
412 | #ifdef CONFIG_X86_64 | ||
413 | static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, | ||
414 | unsigned long error_code) | ||
415 | { | ||
416 | unsigned long flags = oops_begin(); | ||
417 | struct task_struct *tsk; | ||
418 | |||
419 | printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", | ||
420 | current->comm, address); | ||
421 | dump_pagetable(address); | ||
422 | tsk = current; | ||
423 | tsk->thread.cr2 = address; | ||
424 | tsk->thread.trap_no = 14; | ||
425 | tsk->thread.error_code = error_code; | ||
426 | if (__die("Bad pagetable", regs, error_code)) | ||
427 | regs = NULL; | ||
428 | oops_end(flags, regs, SIGKILL); | ||
429 | } | ||
430 | #endif | ||
431 | |||
355 | /* | 432 | /* |
356 | * Handle a fault on the vmalloc or module mapping area | 433 | * Handle a fault on the vmalloc or module mapping area |
357 | * | 434 | * |
@@ -706,6 +783,7 @@ do_sigbus: | |||
706 | 783 | ||
707 | void vmalloc_sync_all(void) | 784 | void vmalloc_sync_all(void) |
708 | { | 785 | { |
786 | #ifdef CONFIG_X86_32 | ||
709 | /* | 787 | /* |
710 | * Note that races in the updates of insync and start aren't | 788 | * Note that races in the updates of insync and start aren't |
711 | * problematic: insync can only get set bits added, and updates to | 789 | * problematic: insync can only get set bits added, and updates to |
@@ -740,4 +818,42 @@ void vmalloc_sync_all(void) | |||
740 | if (address == start && test_bit(pgd_index(address), insync)) | 818 | if (address == start && test_bit(pgd_index(address), insync)) |
741 | start = address + PGDIR_SIZE; | 819 | start = address + PGDIR_SIZE; |
742 | } | 820 | } |
821 | #else /* CONFIG_X86_64 */ | ||
822 | /* | ||
823 | * Note that races in the updates of insync and start aren't | ||
824 | * problematic: insync can only get set bits added, and updates to | ||
825 | * start are only improving performance (without affecting correctness | ||
826 | * if undone). | ||
827 | */ | ||
828 | static DECLARE_BITMAP(insync, PTRS_PER_PGD); | ||
829 | static unsigned long start = VMALLOC_START & PGDIR_MASK; | ||
830 | unsigned long address; | ||
831 | |||
832 | for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) { | ||
833 | if (!test_bit(pgd_index(address), insync)) { | ||
834 | const pgd_t *pgd_ref = pgd_offset_k(address); | ||
835 | struct page *page; | ||
836 | |||
837 | if (pgd_none(*pgd_ref)) | ||
838 | continue; | ||
839 | spin_lock(&pgd_lock); | ||
840 | list_for_each_entry(page, &pgd_list, lru) { | ||
841 | pgd_t *pgd; | ||
842 | pgd = (pgd_t *)page_address(page) + pgd_index(address); | ||
843 | if (pgd_none(*pgd)) | ||
844 | set_pgd(pgd, *pgd_ref); | ||
845 | else | ||
846 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); | ||
847 | } | ||
848 | spin_unlock(&pgd_lock); | ||
849 | set_bit(pgd_index(address), insync); | ||
850 | } | ||
851 | if (address == start) | ||
852 | start = address + PGDIR_SIZE; | ||
853 | } | ||
854 | /* Check that there is no need to do the same for the modules area. */ | ||
855 | BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL)); | ||
856 | BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) == | ||
857 | (__START_KERNEL & PGDIR_MASK))); | ||
858 | #endif | ||
743 | } | 859 | } |