diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/cacheflush.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/ftrace.h | 25 | ||||
-rw-r--r-- | arch/x86/include/asm/ptrace-abi.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/ftrace.c | 141 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 5 | ||||
-rw-r--r-- | arch/x86/kvm/Kconfig | 3 | ||||
-rw-r--r-- | arch/x86/mm/init_32.c | 35 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 37 |
11 files changed, 115 insertions, 151 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9c39095b33fc..8fc9a847cf48 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -34,6 +34,7 @@ config X86 | |||
34 | select HAVE_FUNCTION_TRACER | 34 | select HAVE_FUNCTION_TRACER |
35 | select HAVE_FUNCTION_GRAPH_TRACER | 35 | select HAVE_FUNCTION_GRAPH_TRACER |
36 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 36 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
37 | select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE | ||
37 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) | 38 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) |
38 | select HAVE_ARCH_KGDB if !X86_VOYAGER | 39 | select HAVE_ARCH_KGDB if !X86_VOYAGER |
39 | select HAVE_ARCH_TRACEHOOK | 40 | select HAVE_ARCH_TRACEHOOK |
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 |
105 | void mark_rodata_ro(void); | 105 | void mark_rodata_ro(void); |
106 | extern const int rodata_test_data; | 106 | extern const int rodata_test_data; |
107 | void set_kernel_text_rw(void); | ||
108 | void set_kernel_text_ro(void); | ||
109 | #else | ||
110 | static inline void set_kernel_text_rw(void) { } | ||
111 | static 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/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index b55b4a7fbefd..db24c2278be0 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h | |||
@@ -55,29 +55,4 @@ struct dyn_arch_ftrace { | |||
55 | #endif /* __ASSEMBLY__ */ | 55 | #endif /* __ASSEMBLY__ */ |
56 | #endif /* CONFIG_FUNCTION_TRACER */ | 56 | #endif /* CONFIG_FUNCTION_TRACER */ |
57 | 57 | ||
58 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
59 | |||
60 | #ifndef __ASSEMBLY__ | ||
61 | |||
62 | /* | ||
63 | * Stack of return addresses for functions | ||
64 | * of a thread. | ||
65 | * Used in struct thread_info | ||
66 | */ | ||
67 | struct ftrace_ret_stack { | ||
68 | unsigned long ret; | ||
69 | unsigned long func; | ||
70 | unsigned long long calltime; | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * Primary handler of a function return. | ||
75 | * It relays on ftrace_return_to_handler. | ||
76 | * Defined in entry_32/64.S | ||
77 | */ | ||
78 | extern void return_to_handler(void); | ||
79 | |||
80 | #endif /* __ASSEMBLY__ */ | ||
81 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
82 | |||
83 | #endif /* _ASM_X86_FTRACE_H */ | 58 | #endif /* _ASM_X86_FTRACE_H */ |
diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h index 8e0f8d199e05..86723035a515 100644 --- a/arch/x86/include/asm/ptrace-abi.h +++ b/arch/x86/include/asm/ptrace-abi.h | |||
@@ -80,8 +80,6 @@ | |||
80 | 80 | ||
81 | #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ | 81 | #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ |
82 | 82 | ||
83 | #ifdef CONFIG_X86_PTRACE_BTS | ||
84 | |||
85 | #ifndef __ASSEMBLY__ | 83 | #ifndef __ASSEMBLY__ |
86 | #include <linux/types.h> | 84 | #include <linux/types.h> |
87 | 85 | ||
@@ -140,6 +138,5 @@ struct ptrace_bts_config { | |||
140 | BTS records are read from oldest to newest. | 138 | BTS records are read from oldest to newest. |
141 | Returns number of BTS records drained. | 139 | Returns number of BTS records drained. |
142 | */ | 140 | */ |
143 | #endif /* CONFIG_X86_PTRACE_BTS */ | ||
144 | 141 | ||
145 | #endif /* _ASM_X86_PTRACE_ABI_H */ | 142 | #endif /* _ASM_X86_PTRACE_ABI_H */ |
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 4b1c319d30c3..c5d737cdb365 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/cpufreq.h> | 33 | #include <linux/cpufreq.h> |
34 | #include <linux/compiler.h> | 34 | #include <linux/compiler.h> |
35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
36 | #include <linux/ftrace.h> | 36 | #include <trace/power.h> |
37 | 37 | ||
38 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
39 | #include <acpi/processor.h> | 39 | #include <acpi/processor.h> |
@@ -70,6 +70,8 @@ struct acpi_cpufreq_data { | |||
70 | 70 | ||
71 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data); | 71 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data); |
72 | 72 | ||
73 | DEFINE_TRACE(power_mark); | ||
74 | |||
73 | /* acpi_perf_data is a pointer to percpu data. */ | 75 | /* acpi_perf_data is a pointer to percpu data. */ |
74 | static struct acpi_processor_performance *acpi_perf_data; | 76 | static struct acpi_processor_performance *acpi_perf_data; |
75 | 77 | ||
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 6b1f6f6f8661..4325165753d8 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -10,10 +10,12 @@ | |||
10 | #include <linux/kdebug.h> | 10 | #include <linux/kdebug.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/ptrace.h> | 12 | #include <linux/ptrace.h> |
13 | #include <linux/ftrace.h> | ||
13 | #include <linux/kexec.h> | 14 | #include <linux/kexec.h> |
14 | #include <linux/bug.h> | 15 | #include <linux/bug.h> |
15 | #include <linux/nmi.h> | 16 | #include <linux/nmi.h> |
16 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
18 | #include <linux/ftrace.h> | ||
17 | 19 | ||
18 | #include <asm/stacktrace.h> | 20 | #include <asm/stacktrace.h> |
19 | 21 | ||
@@ -195,6 +197,11 @@ unsigned __kprobes long oops_begin(void) | |||
195 | int cpu; | 197 | int cpu; |
196 | unsigned long flags; | 198 | unsigned long flags; |
197 | 199 | ||
200 | /* notify the hw-branch tracer so it may disable tracing and | ||
201 | add the last trace to the trace buffer - | ||
202 | the earlier this happens, the more useful the trace. */ | ||
203 | trace_hw_branch_oops(); | ||
204 | |||
198 | oops_enter(); | 205 | oops_enter(); |
199 | 206 | ||
200 | /* racy, but better than risking deadlock. */ | 207 | /* racy, but better than risking deadlock. */ |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 231bdd3c5b1c..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 | ||
30 | int ftrace_arch_code_modify_prepare(void) | ||
31 | { | ||
32 | set_kernel_text_rw(); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | int ftrace_arch_code_modify_post_process(void) | ||
37 | { | ||
38 | set_kernel_text_ro(); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
29 | union ftrace_code_union { | 42 | union ftrace_code_union { |
30 | char code[MCOUNT_INSN_SIZE]; | 43 | char code[MCOUNT_INSN_SIZE]; |
31 | struct { | 44 | struct { |
@@ -82,7 +95,7 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | |||
82 | * are the same as what exists. | 95 | * are the same as what exists. |
83 | */ | 96 | */ |
84 | 97 | ||
85 | static atomic_t in_nmi = ATOMIC_INIT(0); | 98 | static atomic_t nmi_running = ATOMIC_INIT(0); |
86 | static int mod_code_status; /* holds return value of text write */ | 99 | static int mod_code_status; /* holds return value of text write */ |
87 | static int mod_code_write; /* set when NMI should do the write */ | 100 | static int mod_code_write; /* set when NMI should do the write */ |
88 | static void *mod_code_ip; /* holds the IP to write to */ | 101 | static void *mod_code_ip; /* holds the IP to write to */ |
@@ -111,12 +124,16 @@ 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 | ||
116 | void ftrace_nmi_enter(void) | 133 | void ftrace_nmi_enter(void) |
117 | { | 134 | { |
118 | atomic_inc(&in_nmi); | 135 | atomic_inc(&nmi_running); |
119 | /* Must have in_nmi seen before reading write flag */ | 136 | /* Must have nmi_running seen before reading write flag */ |
120 | smp_mb(); | 137 | smp_mb(); |
121 | if (mod_code_write) { | 138 | if (mod_code_write) { |
122 | ftrace_mod_code(); | 139 | ftrace_mod_code(); |
@@ -126,22 +143,21 @@ void ftrace_nmi_enter(void) | |||
126 | 143 | ||
127 | void ftrace_nmi_exit(void) | 144 | void ftrace_nmi_exit(void) |
128 | { | 145 | { |
129 | /* Finish all executions before clearing in_nmi */ | 146 | /* Finish all executions before clearing nmi_running */ |
130 | smp_wmb(); | 147 | smp_wmb(); |
131 | atomic_dec(&in_nmi); | 148 | atomic_dec(&nmi_running); |
132 | } | 149 | } |
133 | 150 | ||
134 | static void wait_for_nmi(void) | 151 | static void wait_for_nmi(void) |
135 | { | 152 | { |
136 | int waited = 0; | 153 | if (!atomic_read(&nmi_running)) |
154 | return; | ||
137 | 155 | ||
138 | while (atomic_read(&in_nmi)) { | 156 | do { |
139 | waited = 1; | ||
140 | cpu_relax(); | 157 | cpu_relax(); |
141 | } | 158 | } while (atomic_read(&nmi_running)); |
142 | 159 | ||
143 | if (waited) | 160 | nmi_wait_count++; |
144 | nmi_wait_count++; | ||
145 | } | 161 | } |
146 | 162 | ||
147 | static int | 163 | static int |
@@ -368,100 +384,8 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
368 | return ftrace_mod_jmp(ip, old_offset, new_offset); | 384 | return ftrace_mod_jmp(ip, old_offset, new_offset); |
369 | } | 385 | } |
370 | 386 | ||
371 | #else /* CONFIG_DYNAMIC_FTRACE */ | ||
372 | |||
373 | /* | ||
374 | * These functions are picked from those used on | ||
375 | * this page for dynamic ftrace. They have been | ||
376 | * simplified to ignore all traces in NMI context. | ||
377 | */ | ||
378 | static atomic_t in_nmi; | ||
379 | |||
380 | void ftrace_nmi_enter(void) | ||
381 | { | ||
382 | atomic_inc(&in_nmi); | ||
383 | } | ||
384 | |||
385 | void ftrace_nmi_exit(void) | ||
386 | { | ||
387 | atomic_dec(&in_nmi); | ||
388 | } | ||
389 | |||
390 | #endif /* !CONFIG_DYNAMIC_FTRACE */ | 387 | #endif /* !CONFIG_DYNAMIC_FTRACE */ |
391 | 388 | ||
392 | /* Add a function return address to the trace stack on thread info.*/ | ||
393 | static int push_return_trace(unsigned long ret, unsigned long long time, | ||
394 | unsigned long func, int *depth) | ||
395 | { | ||
396 | int index; | ||
397 | |||
398 | if (!current->ret_stack) | ||
399 | return -EBUSY; | ||
400 | |||
401 | /* The return trace stack is full */ | ||
402 | if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { | ||
403 | atomic_inc(¤t->trace_overrun); | ||
404 | return -EBUSY; | ||
405 | } | ||
406 | |||
407 | index = ++current->curr_ret_stack; | ||
408 | barrier(); | ||
409 | current->ret_stack[index].ret = ret; | ||
410 | current->ret_stack[index].func = func; | ||
411 | current->ret_stack[index].calltime = time; | ||
412 | *depth = index; | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | /* Retrieve a function return address to the trace stack on thread info.*/ | ||
418 | static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) | ||
419 | { | ||
420 | int index; | ||
421 | |||
422 | index = current->curr_ret_stack; | ||
423 | |||
424 | if (unlikely(index < 0)) { | ||
425 | ftrace_graph_stop(); | ||
426 | WARN_ON(1); | ||
427 | /* Might as well panic, otherwise we have no where to go */ | ||
428 | *ret = (unsigned long)panic; | ||
429 | return; | ||
430 | } | ||
431 | |||
432 | *ret = current->ret_stack[index].ret; | ||
433 | trace->func = current->ret_stack[index].func; | ||
434 | trace->calltime = current->ret_stack[index].calltime; | ||
435 | trace->overrun = atomic_read(¤t->trace_overrun); | ||
436 | trace->depth = index; | ||
437 | barrier(); | ||
438 | current->curr_ret_stack--; | ||
439 | |||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Send the trace to the ring-buffer. | ||
444 | * @return the original return address. | ||
445 | */ | ||
446 | unsigned long ftrace_return_to_handler(void) | ||
447 | { | ||
448 | struct ftrace_graph_ret trace; | ||
449 | unsigned long ret; | ||
450 | |||
451 | pop_return_trace(&trace, &ret); | ||
452 | trace.rettime = cpu_clock(raw_smp_processor_id()); | ||
453 | ftrace_graph_return(&trace); | ||
454 | |||
455 | if (unlikely(!ret)) { | ||
456 | ftrace_graph_stop(); | ||
457 | WARN_ON(1); | ||
458 | /* Might as well panic. What else to do? */ | ||
459 | ret = (unsigned long)panic; | ||
460 | } | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | /* | 389 | /* |
466 | * Hook the return address and push it in the stack of return addrs | 390 | * Hook the return address and push it in the stack of return addrs |
467 | * in current thread info. | 391 | * in current thread info. |
@@ -476,7 +400,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | |||
476 | &return_to_handler; | 400 | &return_to_handler; |
477 | 401 | ||
478 | /* Nmi's are currently unsupported */ | 402 | /* Nmi's are currently unsupported */ |
479 | if (unlikely(atomic_read(&in_nmi))) | 403 | if (unlikely(in_nmi())) |
480 | return; | 404 | return; |
481 | 405 | ||
482 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | 406 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) |
@@ -512,16 +436,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | |||
512 | return; | 436 | return; |
513 | } | 437 | } |
514 | 438 | ||
515 | if (unlikely(!__kernel_text_address(old))) { | ||
516 | ftrace_graph_stop(); | ||
517 | *parent = old; | ||
518 | WARN_ON(1); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | calltime = cpu_clock(raw_smp_processor_id()); | 439 | calltime = cpu_clock(raw_smp_processor_id()); |
523 | 440 | ||
524 | if (push_return_trace(old, calltime, | 441 | if (ftrace_push_return_trace(old, calltime, |
525 | self_addr, &trace.depth) == -EBUSY) { | 442 | self_addr, &trace.depth) == -EBUSY) { |
526 | *parent = old; | 443 | *parent = old; |
527 | return; | 444 | return; |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 6d12f7e37f8c..23b328edc2b3 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/pm.h> | 9 | #include <linux/pm.h> |
10 | #include <linux/clockchips.h> | 10 | #include <linux/clockchips.h> |
11 | #include <linux/ftrace.h> | 11 | #include <trace/power.h> |
12 | #include <asm/system.h> | 12 | #include <asm/system.h> |
13 | #include <asm/apic.h> | 13 | #include <asm/apic.h> |
14 | 14 | ||
@@ -19,6 +19,9 @@ EXPORT_SYMBOL(idle_nomwait); | |||
19 | 19 | ||
20 | struct kmem_cache *task_xstate_cachep; | 20 | struct kmem_cache *task_xstate_cachep; |
21 | 21 | ||
22 | DEFINE_TRACE(power_start); | ||
23 | DEFINE_TRACE(power_end); | ||
24 | |||
22 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | 25 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
23 | { | 26 | { |
24 | *dst = *src; | 27 | *dst = *src; |
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index b81125f0bdee..c7da3683f4c5 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig | |||
@@ -55,7 +55,8 @@ config KVM_AMD | |||
55 | 55 | ||
56 | config KVM_TRACE | 56 | config KVM_TRACE |
57 | bool "KVM trace support" | 57 | bool "KVM trace support" |
58 | depends on KVM && MARKERS && SYSFS | 58 | depends on KVM && SYSFS |
59 | select MARKERS | ||
59 | select RELAY | 60 | select RELAY |
60 | select DEBUG_FS | 61 | select DEBUG_FS |
61 | default n | 62 | default n |
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) | |||
1155 | const int rodata_test_data = 0xC3; | 1155 | const int rodata_test_data = 0xC3; |
1156 | EXPORT_SYMBOL_GPL(rodata_test_data); | 1156 | EXPORT_SYMBOL_GPL(rodata_test_data); |
1157 | 1157 | ||
1158 | static int kernel_set_to_readonly; | ||
1159 | |||
1160 | void 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 | |||
1174 | void 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 | |||
1158 | void mark_rodata_ro(void) | 1188 | void 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) | |||
986 | const int rodata_test_data = 0xC3; | 986 | const int rodata_test_data = 0xC3; |
987 | EXPORT_SYMBOL_GPL(rodata_test_data); | 987 | EXPORT_SYMBOL_GPL(rodata_test_data); |
988 | 988 | ||
989 | static int kernel_set_to_readonly; | ||
990 | |||
991 | void 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 | |||
1005 | void 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 | |||
989 | void mark_rodata_ro(void) | 1019 | void 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. |