diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-07-10 05:43:00 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-07-10 05:43:00 -0400 |
| commit | bac0c9103b31c3dd83ad9d731dd9834e2ba75e4f (patch) | |
| tree | 702dd6a7ce06d224d594c2293af546b11ac9f51b /arch/x86/mm | |
| parent | 6329d3021bcfa9038621e6e917d98929421d8ec8 (diff) | |
| parent | 98a05ed4bd7774f533ab185fe0bf2fdc58292d7c (diff) | |
Merge branch 'tracing/ftrace' into auto-ftrace-next
Diffstat (limited to 'arch/x86/mm')
| -rw-r--r-- | arch/x86/mm/fault.c | 56 | ||||
| -rw-r--r-- | arch/x86/mm/init_32.c | 4 | ||||
| -rw-r--r-- | arch/x86/mm/init_64.c | 10 |
3 files changed, 68 insertions, 2 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 8bcb6f40ccb6..42394b353c6a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -49,6 +49,60 @@ | |||
| 49 | #define PF_RSVD (1<<3) | 49 | #define PF_RSVD (1<<3) |
| 50 | #define PF_INSTR (1<<4) | 50 | #define PF_INSTR (1<<4) |
| 51 | 51 | ||
| 52 | #ifdef CONFIG_PAGE_FAULT_HANDLERS | ||
| 53 | static HLIST_HEAD(pf_handlers); /* protected by RCU */ | ||
| 54 | static DEFINE_SPINLOCK(pf_handlers_writer); | ||
| 55 | |||
| 56 | void register_page_fault_handler(struct pf_handler *new_pfh) | ||
| 57 | { | ||
| 58 | unsigned long flags; | ||
| 59 | spin_lock_irqsave(&pf_handlers_writer, flags); | ||
| 60 | hlist_add_head_rcu(&new_pfh->hlist, &pf_handlers); | ||
| 61 | spin_unlock_irqrestore(&pf_handlers_writer, flags); | ||
| 62 | } | ||
| 63 | EXPORT_SYMBOL_GPL(register_page_fault_handler); | ||
| 64 | |||
| 65 | /** | ||
| 66 | * unregister_page_fault_handler: | ||
| 67 | * The caller must ensure @old_pfh is not in use anymore before freeing it. | ||
| 68 | * This function does not guarantee it. The list of handlers is protected by | ||
| 69 | * RCU, so you can do this by e.g. calling synchronize_rcu(). | ||
| 70 | */ | ||
| 71 | void unregister_page_fault_handler(struct pf_handler *old_pfh) | ||
| 72 | { | ||
| 73 | unsigned long flags; | ||
| 74 | spin_lock_irqsave(&pf_handlers_writer, flags); | ||
| 75 | hlist_del_rcu(&old_pfh->hlist); | ||
| 76 | spin_unlock_irqrestore(&pf_handlers_writer, flags); | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL_GPL(unregister_page_fault_handler); | ||
| 79 | #endif | ||
| 80 | |||
| 81 | /* returns non-zero if do_page_fault() should return */ | ||
| 82 | static int handle_custom_pf(struct pt_regs *regs, unsigned long error_code, | ||
| 83 | unsigned long address) | ||
| 84 | { | ||
| 85 | #ifdef CONFIG_PAGE_FAULT_HANDLERS | ||
| 86 | int ret = 0; | ||
| 87 | struct pf_handler *cur; | ||
| 88 | struct hlist_node *ncur; | ||
| 89 | |||
| 90 | if (hlist_empty(&pf_handlers)) | ||
| 91 | return 0; | ||
| 92 | |||
| 93 | rcu_read_lock(); | ||
| 94 | hlist_for_each_entry_rcu(cur, ncur, &pf_handlers, hlist) { | ||
| 95 | ret = cur->handler(regs, error_code, address); | ||
| 96 | if (ret) | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | rcu_read_unlock(); | ||
| 100 | return ret; | ||
| 101 | #else | ||
| 102 | return 0; | ||
| 103 | #endif | ||
| 104 | } | ||
| 105 | |||
| 52 | static inline int notify_page_fault(struct pt_regs *regs) | 106 | static inline int notify_page_fault(struct pt_regs *regs) |
| 53 | { | 107 | { |
| 54 | #ifdef CONFIG_KPROBES | 108 | #ifdef CONFIG_KPROBES |
| @@ -606,6 +660,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
| 606 | 660 | ||
| 607 | if (notify_page_fault(regs)) | 661 | if (notify_page_fault(regs)) |
| 608 | return; | 662 | return; |
| 663 | if (handle_custom_pf(regs, error_code, address)) | ||
| 664 | return; | ||
| 609 | 665 | ||
| 610 | /* | 666 | /* |
| 611 | * We fault-in kernel-space virtual memory on-demand. The | 667 | * We fault-in kernel-space virtual memory on-demand. The |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index ec30d10154b6..f96eca21ad8f 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
| @@ -710,6 +710,8 @@ void mark_rodata_ro(void) | |||
| 710 | unsigned long start = PFN_ALIGN(_text); | 710 | unsigned long start = PFN_ALIGN(_text); |
| 711 | unsigned long size = PFN_ALIGN(_etext) - start; | 711 | unsigned long size = PFN_ALIGN(_etext) - start; |
| 712 | 712 | ||
| 713 | #ifndef CONFIG_DYNAMIC_FTRACE | ||
| 714 | /* Dynamic tracing modifies the kernel text section */ | ||
| 713 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); | 715 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); |
| 714 | printk(KERN_INFO "Write protecting the kernel text: %luk\n", | 716 | printk(KERN_INFO "Write protecting the kernel text: %luk\n", |
| 715 | size >> 10); | 717 | size >> 10); |
| @@ -722,6 +724,8 @@ void mark_rodata_ro(void) | |||
| 722 | printk(KERN_INFO "Testing CPA: write protecting again\n"); | 724 | printk(KERN_INFO "Testing CPA: write protecting again\n"); |
| 723 | set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); | 725 | set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); |
| 724 | #endif | 726 | #endif |
| 727 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
| 728 | |||
| 725 | start += size; | 729 | start += size; |
| 726 | size = (unsigned long)__end_rodata - start; | 730 | size = (unsigned long)__end_rodata - start; |
| 727 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); | 731 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 819dad973b13..17c0a6138a53 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
| @@ -767,6 +767,13 @@ EXPORT_SYMBOL_GPL(rodata_test_data); | |||
| 767 | void mark_rodata_ro(void) | 767 | void mark_rodata_ro(void) |
| 768 | { | 768 | { |
| 769 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); | 769 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); |
| 770 | unsigned long rodata_start = | ||
| 771 | ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; | ||
| 772 | |||
| 773 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 774 | /* Dynamic tracing modifies the kernel text section */ | ||
| 775 | start = rodata_start; | ||
| 776 | #endif | ||
| 770 | 777 | ||
| 771 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", | 778 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", |
| 772 | (end - start) >> 10); | 779 | (end - start) >> 10); |
| @@ -776,8 +783,7 @@ void mark_rodata_ro(void) | |||
| 776 | * The rodata section (but not the kernel text!) should also be | 783 | * The rodata section (but not the kernel text!) should also be |
| 777 | * not-executable. | 784 | * not-executable. |
| 778 | */ | 785 | */ |
| 779 | start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; | 786 | set_memory_nx(rodata_start, (end - rodata_start) >> PAGE_SHIFT); |
| 780 | set_memory_nx(start, (end - start) >> PAGE_SHIFT); | ||
| 781 | 787 | ||
| 782 | rodata_test(); | 788 | rodata_test(); |
| 783 | 789 | ||
