diff options
Diffstat (limited to 'arch/x86/mm/fault.c')
| -rw-r--r-- | arch/x86/mm/fault.c | 97 |
1 files changed, 30 insertions, 67 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 8bcb6f40ccb6..d0f5fce77d95 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -55,11 +55,7 @@ static inline int notify_page_fault(struct pt_regs *regs) | |||
| 55 | int ret = 0; | 55 | int ret = 0; |
| 56 | 56 | ||
| 57 | /* kprobe_running() needs smp_processor_id() */ | 57 | /* kprobe_running() needs smp_processor_id() */ |
| 58 | #ifdef CONFIG_X86_32 | ||
| 59 | if (!user_mode_vm(regs)) { | 58 | if (!user_mode_vm(regs)) { |
| 60 | #else | ||
| 61 | if (!user_mode(regs)) { | ||
| 62 | #endif | ||
| 63 | preempt_disable(); | 59 | preempt_disable(); |
| 64 | if (kprobe_running() && kprobe_fault_handler(regs, 14)) | 60 | if (kprobe_running() && kprobe_fault_handler(regs, 14)) |
| 65 | ret = 1; | 61 | ret = 1; |
| @@ -396,11 +392,7 @@ static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, | |||
| 396 | printk(KERN_CONT "NULL pointer dereference"); | 392 | printk(KERN_CONT "NULL pointer dereference"); |
| 397 | else | 393 | else |
| 398 | printk(KERN_CONT "paging request"); | 394 | printk(KERN_CONT "paging request"); |
| 399 | #ifdef CONFIG_X86_32 | 395 | printk(KERN_CONT " at %p\n", (void *) address); |
| 400 | printk(KERN_CONT " at %08lx\n", address); | ||
| 401 | #else | ||
| 402 | printk(KERN_CONT " at %016lx\n", address); | ||
| 403 | #endif | ||
| 404 | printk(KERN_ALERT "IP:"); | 396 | printk(KERN_ALERT "IP:"); |
| 405 | printk_address(regs->ip, 1); | 397 | printk_address(regs->ip, 1); |
| 406 | dump_pagetable(address); | 398 | dump_pagetable(address); |
| @@ -800,14 +792,10 @@ bad_area_nosemaphore: | |||
| 800 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && | 792 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && |
| 801 | printk_ratelimit()) { | 793 | printk_ratelimit()) { |
| 802 | printk( | 794 | printk( |
| 803 | #ifdef CONFIG_X86_32 | 795 | "%s%s[%d]: segfault at %lx ip %p sp %p error %lx", |
| 804 | "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx", | ||
| 805 | #else | ||
| 806 | "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx", | ||
| 807 | #endif | ||
| 808 | task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, | 796 | task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, |
| 809 | tsk->comm, task_pid_nr(tsk), address, regs->ip, | 797 | tsk->comm, task_pid_nr(tsk), address, |
| 810 | regs->sp, error_code); | 798 | (void *) regs->ip, (void *) regs->sp, error_code); |
| 811 | print_vma_addr(" in ", regs->ip); | 799 | print_vma_addr(" in ", regs->ip); |
| 812 | printk("\n"); | 800 | printk("\n"); |
| 813 | } | 801 | } |
| @@ -915,14 +903,7 @@ LIST_HEAD(pgd_list); | |||
| 915 | void vmalloc_sync_all(void) | 903 | void vmalloc_sync_all(void) |
| 916 | { | 904 | { |
| 917 | #ifdef CONFIG_X86_32 | 905 | #ifdef CONFIG_X86_32 |
| 918 | /* | 906 | unsigned long start = VMALLOC_START & PGDIR_MASK; |
| 919 | * Note that races in the updates of insync and start aren't | ||
| 920 | * problematic: insync can only get set bits added, and updates to | ||
| 921 | * start are only improving performance (without affecting correctness | ||
| 922 | * if undone). | ||
| 923 | */ | ||
| 924 | static DECLARE_BITMAP(insync, PTRS_PER_PGD); | ||
| 925 | static unsigned long start = TASK_SIZE; | ||
| 926 | unsigned long address; | 907 | unsigned long address; |
| 927 | 908 | ||
| 928 | if (SHARED_KERNEL_PMD) | 909 | if (SHARED_KERNEL_PMD) |
| @@ -930,56 +911,38 @@ void vmalloc_sync_all(void) | |||
| 930 | 911 | ||
| 931 | BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK); | 912 | BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK); |
| 932 | for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) { | 913 | for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) { |
| 933 | if (!test_bit(pgd_index(address), insync)) { | 914 | unsigned long flags; |
| 934 | unsigned long flags; | 915 | struct page *page; |
| 935 | struct page *page; | 916 | |
| 936 | 917 | spin_lock_irqsave(&pgd_lock, flags); | |
| 937 | spin_lock_irqsave(&pgd_lock, flags); | 918 | list_for_each_entry(page, &pgd_list, lru) { |
| 938 | list_for_each_entry(page, &pgd_list, lru) { | 919 | if (!vmalloc_sync_one(page_address(page), |
| 939 | if (!vmalloc_sync_one(page_address(page), | 920 | address)) |
| 940 | address)) | 921 | break; |
| 941 | break; | ||
| 942 | } | ||
| 943 | spin_unlock_irqrestore(&pgd_lock, flags); | ||
| 944 | if (!page) | ||
| 945 | set_bit(pgd_index(address), insync); | ||
| 946 | } | 922 | } |
| 947 | if (address == start && test_bit(pgd_index(address), insync)) | 923 | spin_unlock_irqrestore(&pgd_lock, flags); |
| 948 | start = address + PGDIR_SIZE; | ||
| 949 | } | 924 | } |
| 950 | #else /* CONFIG_X86_64 */ | 925 | #else /* CONFIG_X86_64 */ |
| 951 | /* | 926 | unsigned long start = VMALLOC_START & PGDIR_MASK; |
| 952 | * Note that races in the updates of insync and start aren't | ||
| 953 | * problematic: insync can only get set bits added, and updates to | ||
| 954 | * start are only improving performance (without affecting correctness | ||
| 955 | * if undone). | ||
| 956 | */ | ||
| 957 | static DECLARE_BITMAP(insync, PTRS_PER_PGD); | ||
| 958 | static unsigned long start = VMALLOC_START & PGDIR_MASK; | ||
| 959 | unsigned long address; | 927 | unsigned long address; |
| 960 | 928 | ||
| 961 | for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) { | 929 | for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) { |
| 962 | if (!test_bit(pgd_index(address), insync)) { | 930 | const pgd_t *pgd_ref = pgd_offset_k(address); |
| 963 | const pgd_t *pgd_ref = pgd_offset_k(address); | 931 | unsigned long flags; |
| 964 | unsigned long flags; | 932 | struct page *page; |
| 965 | struct page *page; | 933 | |
| 966 | 934 | if (pgd_none(*pgd_ref)) | |
| 967 | if (pgd_none(*pgd_ref)) | 935 | continue; |
| 968 | continue; | 936 | spin_lock_irqsave(&pgd_lock, flags); |
| 969 | spin_lock_irqsave(&pgd_lock, flags); | 937 | list_for_each_entry(page, &pgd_list, lru) { |
| 970 | list_for_each_entry(page, &pgd_list, lru) { | 938 | pgd_t *pgd; |
| 971 | pgd_t *pgd; | 939 | pgd = (pgd_t *)page_address(page) + pgd_index(address); |
| 972 | pgd = (pgd_t *)page_address(page) + pgd_index(address); | 940 | if (pgd_none(*pgd)) |
| 973 | if (pgd_none(*pgd)) | 941 | set_pgd(pgd, *pgd_ref); |
| 974 | set_pgd(pgd, *pgd_ref); | 942 | else |
| 975 | else | 943 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); |
| 976 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); | ||
| 977 | } | ||
| 978 | spin_unlock_irqrestore(&pgd_lock, flags); | ||
| 979 | set_bit(pgd_index(address), insync); | ||
| 980 | } | 944 | } |
| 981 | if (address == start) | 945 | spin_unlock_irqrestore(&pgd_lock, flags); |
| 982 | start = address + PGDIR_SIZE; | ||
| 983 | } | 946 | } |
| 984 | #endif | 947 | #endif |
| 985 | } | 948 | } |
