aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-22 12:12:01 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-22 12:12:01 -0500
commitc478f8786973d6d7552c652ddad3f6fd86b5af28 (patch)
tree39967f4bb9a35d626584bd46f1acd916c6b5278d
parent843adf2379c18ed9a1b7493ee208bfd5512732e0 (diff)
parent4377245aa93b65b6597e4b7bb460fb9abc48b56b (diff)
Merge branch 'tip/x86/ftrace' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/ftrace
Conflicts: include/linux/ftrace.h kernel/trace/ftrace.c
-rw-r--r--arch/x86/include/asm/cacheflush.h5
-rw-r--r--arch/x86/kernel/ftrace.c17
-rw-r--r--arch/x86/kernel/vmiclock_32.c5
-rw-r--r--arch/x86/mm/init_32.c35
-rw-r--r--arch/x86/mm/init_64.c37
-rw-r--r--arch/x86/mm/pageattr.c15
-rw-r--r--include/linux/ftrace.h3
-rw-r--r--kernel/trace/ftrace.c33
8 files changed, 130 insertions, 20 deletions
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 2f8466540fb5..6145063cfe0e 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -104,6 +104,11 @@ void clflush_cache_range(void *addr, unsigned int size);
104#ifdef CONFIG_DEBUG_RODATA 104#ifdef CONFIG_DEBUG_RODATA
105void mark_rodata_ro(void); 105void mark_rodata_ro(void);
106extern const int rodata_test_data; 106extern const int rodata_test_data;
107void set_kernel_text_rw(void);
108void set_kernel_text_ro(void);
109#else
110static inline void set_kernel_text_rw(void) { }
111static inline void set_kernel_text_ro(void) { }
107#endif 112#endif
108 113
109#ifdef CONFIG_DEBUG_RODATA_TEST 114#ifdef CONFIG_DEBUG_RODATA_TEST
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index c2e057d9f88c..3925ec0184b1 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -18,6 +18,7 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/list.h> 19#include <linux/list.h>
20 20
21#include <asm/cacheflush.h>
21#include <asm/ftrace.h> 22#include <asm/ftrace.h>
22#include <linux/ftrace.h> 23#include <linux/ftrace.h>
23#include <asm/nops.h> 24#include <asm/nops.h>
@@ -26,6 +27,18 @@
26 27
27#ifdef CONFIG_DYNAMIC_FTRACE 28#ifdef CONFIG_DYNAMIC_FTRACE
28 29
30int ftrace_arch_code_modify_prepare(void)
31{
32 set_kernel_text_rw();
33 return 0;
34}
35
36int ftrace_arch_code_modify_post_process(void)
37{
38 set_kernel_text_ro();
39 return 0;
40}
41
29union ftrace_code_union { 42union ftrace_code_union {
30 char code[MCOUNT_INSN_SIZE]; 43 char code[MCOUNT_INSN_SIZE];
31 struct { 44 struct {
@@ -111,6 +124,10 @@ static void ftrace_mod_code(void)
111 */ 124 */
112 mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode, 125 mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
113 MCOUNT_INSN_SIZE); 126 MCOUNT_INSN_SIZE);
127
128 /* if we fail, then kill any new writers */
129 if (mod_code_status)
130 mod_code_write = 0;
114} 131}
115 132
116void ftrace_nmi_enter(void) 133void ftrace_nmi_enter(void)
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
index c4c1f9e09402..bde106cae0a9 100644
--- a/arch/x86/kernel/vmiclock_32.c
+++ b/arch/x86/kernel/vmiclock_32.c
@@ -283,10 +283,13 @@ void __devinit vmi_time_ap_init(void)
283#endif 283#endif
284 284
285/** vmi clocksource */ 285/** vmi clocksource */
286static struct clocksource clocksource_vmi;
286 287
287static cycle_t read_real_cycles(void) 288static cycle_t read_real_cycles(void)
288{ 289{
289 return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL); 290 cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
291 return ret >= clocksource_vmi.cycle_last ?
292 ret : clocksource_vmi.cycle_last;
290} 293}
291 294
292static struct clocksource clocksource_vmi = { 295static struct clocksource clocksource_vmi = {
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 2cef05074413..3eb2ed188a4c 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -1155,17 +1155,47 @@ static noinline int do_test_wp_bit(void)
1155const int rodata_test_data = 0xC3; 1155const int rodata_test_data = 0xC3;
1156EXPORT_SYMBOL_GPL(rodata_test_data); 1156EXPORT_SYMBOL_GPL(rodata_test_data);
1157 1157
1158static int kernel_set_to_readonly;
1159
1160void set_kernel_text_rw(void)
1161{
1162 unsigned long start = PFN_ALIGN(_text);
1163 unsigned long size = PFN_ALIGN(_etext) - start;
1164
1165 if (!kernel_set_to_readonly)
1166 return;
1167
1168 pr_debug("Set kernel text: %lx - %lx for read write\n",
1169 start, start+size);
1170
1171 set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
1172}
1173
1174void set_kernel_text_ro(void)
1175{
1176 unsigned long start = PFN_ALIGN(_text);
1177 unsigned long size = PFN_ALIGN(_etext) - start;
1178
1179 if (!kernel_set_to_readonly)
1180 return;
1181
1182 pr_debug("Set kernel text: %lx - %lx for read only\n",
1183 start, start+size);
1184
1185 set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
1186}
1187
1158void mark_rodata_ro(void) 1188void mark_rodata_ro(void)
1159{ 1189{
1160 unsigned long start = PFN_ALIGN(_text); 1190 unsigned long start = PFN_ALIGN(_text);
1161 unsigned long size = PFN_ALIGN(_etext) - start; 1191 unsigned long size = PFN_ALIGN(_etext) - start;
1162 1192
1163#ifndef CONFIG_DYNAMIC_FTRACE
1164 /* Dynamic tracing modifies the kernel text section */
1165 set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); 1193 set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
1166 printk(KERN_INFO "Write protecting the kernel text: %luk\n", 1194 printk(KERN_INFO "Write protecting the kernel text: %luk\n",
1167 size >> 10); 1195 size >> 10);
1168 1196
1197 kernel_set_to_readonly = 1;
1198
1169#ifdef CONFIG_CPA_DEBUG 1199#ifdef CONFIG_CPA_DEBUG
1170 printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n", 1200 printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
1171 start, start+size); 1201 start, start+size);
@@ -1174,7 +1204,6 @@ void mark_rodata_ro(void)
1174 printk(KERN_INFO "Testing CPA: write protecting again\n"); 1204 printk(KERN_INFO "Testing CPA: write protecting again\n");
1175 set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); 1205 set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
1176#endif 1206#endif
1177#endif /* CONFIG_DYNAMIC_FTRACE */
1178 1207
1179 start += size; 1208 start += size;
1180 size = (unsigned long)__end_rodata - start; 1209 size = (unsigned long)__end_rodata - start;
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index e6d36b490250..63fdc531601d 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -986,21 +986,48 @@ void free_initmem(void)
986const int rodata_test_data = 0xC3; 986const int rodata_test_data = 0xC3;
987EXPORT_SYMBOL_GPL(rodata_test_data); 987EXPORT_SYMBOL_GPL(rodata_test_data);
988 988
989static int kernel_set_to_readonly;
990
991void set_kernel_text_rw(void)
992{
993 unsigned long start = PFN_ALIGN(_stext);
994 unsigned long end = PFN_ALIGN(__start_rodata);
995
996 if (!kernel_set_to_readonly)
997 return;
998
999 pr_debug("Set kernel text: %lx - %lx for read write\n",
1000 start, end);
1001
1002 set_memory_rw(start, (end - start) >> PAGE_SHIFT);
1003}
1004
1005void set_kernel_text_ro(void)
1006{
1007 unsigned long start = PFN_ALIGN(_stext);
1008 unsigned long end = PFN_ALIGN(__start_rodata);
1009
1010 if (!kernel_set_to_readonly)
1011 return;
1012
1013 pr_debug("Set kernel text: %lx - %lx for read only\n",
1014 start, end);
1015
1016 set_memory_ro(start, (end - start) >> PAGE_SHIFT);
1017}
1018
989void mark_rodata_ro(void) 1019void mark_rodata_ro(void)
990{ 1020{
991 unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); 1021 unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
992 unsigned long rodata_start = 1022 unsigned long rodata_start =
993 ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; 1023 ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
994 1024
995#ifdef CONFIG_DYNAMIC_FTRACE
996 /* Dynamic tracing modifies the kernel text section */
997 start = rodata_start;
998#endif
999
1000 printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", 1025 printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
1001 (end - start) >> 10); 1026 (end - start) >> 10);
1002 set_memory_ro(start, (end - start) >> PAGE_SHIFT); 1027 set_memory_ro(start, (end - start) >> PAGE_SHIFT);
1003 1028
1029 kernel_set_to_readonly = 1;
1030
1004 /* 1031 /*
1005 * The rodata section (but not the kernel text!) should also be 1032 * The rodata section (but not the kernel text!) should also be
1006 * not-executable. 1033 * not-executable.
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 8ca0d8566fc8..7be47d1a97e4 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -508,18 +508,13 @@ static int split_large_page(pte_t *kpte, unsigned long address)
508#endif 508#endif
509 509
510 /* 510 /*
511 * Install the new, split up pagetable. Important details here: 511 * Install the new, split up pagetable.
512 * 512 *
513 * On Intel the NX bit of all levels must be cleared to make a 513 * We use the standard kernel pagetable protections for the new
514 * page executable. See section 4.13.2 of Intel 64 and IA-32 514 * pagetable protections, the actual ptes set above control the
515 * Architectures Software Developer's Manual). 515 * primary protection behavior:
516 *
517 * Mark the entry present. The current mapping might be
518 * set to not present, which we preserved above.
519 */ 516 */
520 ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte))); 517 __set_pmd_pte(kpte, address, mk_pte(base, __pgprot(_KERNPG_TABLE)));
521 pgprot_val(ref_prot) |= _PAGE_PRESENT;
522 __set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
523 base = NULL; 518 base = NULL;
524 519
525out_unlock: 520out_unlock:
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 915f4723fc8b..847bb3c48dd0 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -106,6 +106,9 @@ struct ftrace_func_command {
106/* asm/ftrace.h must be defined for archs supporting dynamic ftrace */ 106/* asm/ftrace.h must be defined for archs supporting dynamic ftrace */
107#include <asm/ftrace.h> 107#include <asm/ftrace.h>
108 108
109int ftrace_arch_code_modify_prepare(void);
110int ftrace_arch_code_modify_post_process(void);
111
109struct seq_file; 112struct seq_file;
110 113
111struct ftrace_probe_ops { 114struct ftrace_probe_ops {
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index cf59f4c54745..5a3a06b21eee 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -557,8 +557,11 @@ static void ftrace_replace_code(int enable)
557 if ((system_state == SYSTEM_BOOTING) || 557 if ((system_state == SYSTEM_BOOTING) ||
558 !core_kernel_text(rec->ip)) { 558 !core_kernel_text(rec->ip)) {
559 ftrace_free_rec(rec); 559 ftrace_free_rec(rec);
560 } else 560 } else {
561 ftrace_bug(failed, rec->ip); 561 ftrace_bug(failed, rec->ip);
562 /* Stop processing */
563 return;
564 }
562 } 565 }
563 } while_for_each_ftrace_rec(); 566 } while_for_each_ftrace_rec();
564} 567}
@@ -580,6 +583,24 @@ ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
580 return 1; 583 return 1;
581} 584}
582 585
586/*
587 * archs can override this function if they must do something
588 * before the modifying code is performed.
589 */
590int __weak ftrace_arch_code_modify_prepare(void)
591{
592 return 0;
593}
594
595/*
596 * archs can override this function if they must do something
597 * after the modifying code is performed.
598 */
599int __weak ftrace_arch_code_modify_post_process(void)
600{
601 return 0;
602}
603
583static int __ftrace_modify_code(void *data) 604static int __ftrace_modify_code(void *data)
584{ 605{
585 int *command = data; 606 int *command = data;
@@ -602,7 +623,17 @@ static int __ftrace_modify_code(void *data)
602 623
603static void ftrace_run_update_code(int command) 624static void ftrace_run_update_code(int command)
604{ 625{
626 int ret;
627
628 ret = ftrace_arch_code_modify_prepare();
629 FTRACE_WARN_ON(ret);
630 if (ret)
631 return;
632
605 stop_machine(__ftrace_modify_code, &command, NULL); 633 stop_machine(__ftrace_modify_code, &command, NULL);
634
635 ret = ftrace_arch_code_modify_post_process();
636 FTRACE_WARN_ON(ret);
606} 637}
607 638
608static ftrace_func_t saved_ftrace_func; 639static ftrace_func_t saved_ftrace_func;