linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Nicholas Piggin <npiggin@gmail.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: Nicholas Piggin <npiggin@gmail.com>
Subject: [RFC PATCH] powerpc/64/ftrace: mprofile-kernel patch out mflr
Date: Sat, 13 Apr 2019 11:59:40 +1000	[thread overview]
Message-ID: <20190413015940.31170-1-npiggin@gmail.com> (raw)

The new mprofile-kernel mcount sequence is

  mflr	r0
  bl	_mcount

Dynamic ftrace patches the branch instruction with a noop, but leaves
the mflr. mflr is executed by the branch unit that can only execute one
per cycle on POWER9 and shared with branches, so it would be nice to
avoid it where possible.

This patch is a hacky proof of concept to nop out the mflr. Can we do
this or are there races or other issues with it?
---
 arch/powerpc/kernel/trace/ftrace.c | 77 +++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 52ee24fd353f..ecc75baef23e 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -172,6 +172,19 @@ __ftrace_make_nop(struct module *mod,
 		pr_err("Unexpected instruction %08x around bl _mcount\n", op);
 		return -EINVAL;
 	}
+
+	if (patch_instruction((unsigned int *)ip, pop)) {
+		pr_err("Patching NOP failed.\n");
+		return -EPERM;
+	}
+
+	if (op == PPC_INST_MFLR) {
+		if (patch_instruction((unsigned int *)(ip - 4), pop)) {
+			pr_err("Patching NOP failed.\n");
+			return -EPERM;
+		}
+	}
+
 #else
 	/*
 	 * Our original call site looks like:
@@ -202,13 +215,14 @@ __ftrace_make_nop(struct module *mod,
 		pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, op);
 		return -EINVAL;
 	}
-#endif /* CONFIG_MPROFILE_KERNEL */
 
 	if (patch_instruction((unsigned int *)ip, pop)) {
 		pr_err("Patching NOP failed.\n");
 		return -EPERM;
 	}
 
+#endif /* CONFIG_MPROFILE_KERNEL */
+
 	return 0;
 }
 
@@ -421,6 +435,20 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
 		return -EPERM;
 	}
 
+#ifdef CONFIG_MPROFILE_KERNEL
+	if (probe_kernel_read(&op, (void *)(ip - 4), 4)) {
+		pr_err("Fetching instruction at %lx failed.\n", ip - 4);
+		return -EFAULT;
+	}
+
+	if (op == PPC_INST_MFLR) {
+		if (patch_instruction((unsigned int *)(ip - 4), PPC_INST_NOP)) {
+			pr_err("Patching NOP failed.\n");
+			return -EPERM;
+		}
+	}
+#endif
+
 	return 0;
 }
 
@@ -437,9 +465,20 @@ int ftrace_make_nop(struct module *mod,
 	 */
 	if (test_24bit_addr(ip, addr)) {
 		/* within range */
+		int rc;
+
 		old = ftrace_call_replace(ip, addr, 1);
 		new = PPC_INST_NOP;
-		return ftrace_modify_code(ip, old, new);
+		rc = ftrace_modify_code(ip, old, new);
+		if (rc)
+			return rc;
+#ifdef CONFIG_MPROFILE_KERNEL
+		old = PPC_INST_MFLR;
+		new = PPC_INST_NOP;
+		ftrace_modify_code(ip - 4, old, new);
+		/* old mprofile kernel will error because no mflr */
+#endif
+		return rc;
 	} else if (core_kernel_text(ip))
 		return __ftrace_make_nop_kernel(rec, addr);
 
@@ -562,6 +601,20 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 		return -EINVAL;
 	}
 
+#ifdef CONFIG_MPROFILE_KERNEL
+	if (probe_kernel_read(op, (ip - 4), 4)) {
+		pr_err("Fetching instruction at %lx failed.\n", (unsigned long)(ip - 4));
+		return -EFAULT;
+	}
+
+	if (op[0] == PPC_INST_NOP) {
+		if (patch_instruction((ip - 4), PPC_INST_MFLR)) {
+			pr_err("Patching mflr failed.\n");
+			return -EINVAL;
+		}
+	}
+#endif
+
 	if (patch_branch(ip, tramp, BRANCH_SET_LINK)) {
 		pr_err("REL24 out of range!\n");
 		return -EINVAL;
@@ -650,6 +703,20 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
 		return -EINVAL;
 	}
 
+#ifdef CONFIG_MPROFILE_KERNEL
+	if (probe_kernel_read(&op, (ip - 4), 4)) {
+		pr_err("Fetching instruction at %lx failed.\n", (unsigned long)(ip - 4));
+		return -EFAULT;
+	}
+
+	if (op == PPC_INST_NOP) {
+		if (patch_instruction((ip - 4), PPC_INST_MFLR)) {
+			pr_err("Patching mflr failed.\n");
+			return -EINVAL;
+		}
+	}
+#endif
+
 	if (patch_branch(ip, tramp, BRANCH_SET_LINK)) {
 		pr_err("Error patching branch to ftrace tramp!\n");
 		return -EINVAL;
@@ -670,6 +737,12 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 	 */
 	if (test_24bit_addr(ip, addr)) {
 		/* within range */
+#ifdef CONFIG_MPROFILE_KERNEL
+		old = PPC_INST_NOP;
+		new = PPC_INST_MFLR;
+		ftrace_modify_code(ip - 4, old, new);
+		/* old mprofile-kernel sequence will error because no nop */
+#endif
 		old = PPC_INST_NOP;
 		new = ftrace_call_replace(ip, addr, 1);
 		return ftrace_modify_code(ip, old, new);
-- 
2.20.1


             reply	other threads:[~2019-04-13  2:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-13  1:59 Nicholas Piggin [this message]
2019-04-15  9:42 ` [RFC PATCH] powerpc/64/ftrace: mprofile-kernel patch out mflr Naveen N. Rao
2019-05-13  3:25 ` Michael Ellerman
2019-05-13  6:47   ` Naveen N. Rao
2019-05-13 11:34     ` Michael Ellerman
2019-05-14  8:32       ` Naveen N. Rao
2019-05-15 12:20         ` Michael Ellerman
2019-05-16  5:49         ` Nicholas Piggin
2019-05-16 18:22           ` Naveen N. Rao
2019-05-17  9:12             ` Nicholas Piggin
2019-05-17 17:25               ` Naveen N. Rao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190413015940.31170-1-npiggin@gmail.com \
    --to=npiggin@gmail.com \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).