Blob Blame History Raw
From: Petr Mladek <pmladek@suse.cz>
Date: Tue, 3 Jun 2014 16:19:24 +0200
Subject: [PATCH 3/3] ftrace/x86/xen: use kernel identity mapping only when
 really needed
Patch-mainline: No, Cleaner solution is needed once the related Xen part gets upstream
References: bsc#873195, bsc#886272, bsc#903727, bsc#927725

The dynamic ftrace is not correctly initialized when the kernel is being loaded
using the Xen hypervisor:

[    0.150025] ftrace: allocating 27371 entries in 107 pages
[    0.156405] ------------[ cut here ]------------
[    0.156594] WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:1759 ftrace_bug+0x21f/0x250()
[    0.156909] Modules linked in:
[    0.157126] Supported: Yes
[    0.157282] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.12.20-77.gb9ca132-xen+ #402
[    0.157563] Hardware name:                  /DG965WH, BIOS MQ96510J.86A.1687.2007.0510.0258 05/10/2007
[    0.157869]  ffffffff809c4902 ffffffff80c2fee8 ffffffff80737e9d ffffffff80c2fee8
[    0.158406]  ffffffff800361bc ffff880000004018 0000000000000000 ffffffff80004018
[    0.158915]  0000000000000000 ffff8800abc87820 0000000000000000 ffffffff80004018
[    0.159426] Call Trace:
[    0.159616]  [<ffffffff80008e38>] dump_trace+0x78/0x1c0
[    0.159808]  [<ffffffff80008b00>] show_stack_log_lvl+0xf0/0x150
[    0.160000]  [<ffffffff8000a5b5>] show_stack+0x25/0x50
[    0.160000]  [<ffffffff80737e9d>] dump_stack+0x6a/0x7d
[    0.160000]  [<ffffffff800361bc>] warn_slowpath_common+0x8c/0xc0
[    0.160000]  [<ffffffff800d835f>] ftrace_bug+0x21f/0x250
[    0.160000]  [<ffffffff800d8642>] ftrace_update_code+0x212/0x330
[    0.160000]  [<ffffffff800dac29>] ftrace_process_locs+0x1b9/0x270
[    0.160000]  [<ffffffff80d27ed4>] ftrace_init+0xd2/0x15e
[    0.160000]  [<ffffffff80d14cff>] start_kernel+0x407/0x4c8
[    0.160000] ---[ end trace 0b1cf71181aff5a9 ]---
[    0.160000] ftrace faulted on writing [<ffffffff80004018>] do_one_initcall+0x18/0x1e0

The problem is that the kernel identity mapping is set read only very early
in this situation, see make_readonly() that is called from xen_init_pt().

This patch uses the fact that the kernel text mapping is set read only in
kernel_init() that is called after ftrace_init(). Therefore we could safely
use the kernel text mapping during the ftrace initialization.

The change of the kernel text mapping permissions is signalized by the global
variable "kernel_set_to_readonly", see mark_rodata_ro().

A cleaner solution would be to introduce another global variable that would
signalize the change of permissions in the kernel identity mapping. Then we
could create another helper functions that could modify permission only
of the kernel identity mapping and call them from ftrace_init(). Note that
the existing set_kernel_text_rw() and set_kernel_text_ro() modify the kernel
text mapping as well. But this is complicated and can not be accepted upstream
because the Xen code is still not there.

Signed-off-by: Petr Mladek <pmladek@suse.cz>
---
 arch/x86/kernel/ftrace.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -84,12 +84,20 @@ static unsigned long text_ip_addr(unsign
 	 * the kernel identity mapping instead of the kernel text mapping
 	 * to modify the kernel text.
 	 *
+	 * This is not needed when the kernel is not set read only. In fact,
+	 * the kernel text mapping might be read only when this function is
+	 * called from ftrace_init() and the kernel was loaded under
+	 * Xen hypervisor. In this situation, we could safely use the
+	 * kernel text mapping.
+	 *
 	 * For 32bit kernels, these mappings are same and we can use
 	 * kernel identity mapping to modify code.
 	 */
-	if (within(ip, (unsigned long)_text, (unsigned long)_etext))
+#ifdef CONFIG_STRICT_KERNEL_RWX
+	if (kernel_set_to_readonly &&
+	    within(ip, (unsigned long)_text, (unsigned long)_etext))
 		ip = (unsigned long)__va(__pa_symbol(ip));
-
+#endif
 	return ip;
 }