From: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> To: Steven Rostedt <rostedt@goodmis.org> Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>, bpf@vger.kernel.org, Daniel Borkmann <daniel@iogearbox.net>, Hari Bathini <hbathini@linux.ibm.com>, Jordan Niethe <jniethe5@gmail.com>, Jiri Olsa <jolsa@redhat.com>, linuxppc-dev@lists.ozlabs.org, Michael Ellerman <mpe@ellerman.id.au>, Yauheni Kaliuta <yauheni.kaliuta@redhat.com> Subject: Re: [RFC PATCH 2/3] powerpc/ftrace: Override ftrace_location_lookup() for MPROFILE_KERNEL Date: Thu, 10 Feb 2022 13:58:29 +0000 [thread overview] Message-ID: <1644501274.apfdo9z1hy.naveen@linux.ibm.com> (raw) In-Reply-To: <20220209161017.2bbdb01a@gandalf.local.home> Steven Rostedt wrote: > On Wed, 09 Feb 2022 17:50:09 +0000 > "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote: > >> However, I think we will not be able to use a fixed range. I would like >> to reserve instructions from function entry till the branch to >> _mcount(), and it can be two or four instructions depending on whether a >> function has a global entry point. For this, I am considering adding a >> field in 'struct dyn_arch_ftrace', and a hook in ftrace_process_locs() >> to initialize the same. I may need to override ftrace_cmp_recs(). > > Be careful about adding anything to dyn_arch_ftrace. powerpc already adds > the pointer to the module. Anything you add to that gets multiplied by > thousands of times (which takes up memory). > > At boot up you may see something like: > > ftrace: allocating 45363 entries in 178 pages > > That's 45,363 dyn_arch_ftrace structures. And each module loads their own > as well. To see how many total you have after boot up: > > > # cat /sys/kernel/tracing/dyn_ftrace_total_info > 55974 pages:295 groups: 89 > > That's from the same kernel. Another 10,000 entries were created by modules. > (This was for x86_64) > > What you may be able to do, is to add a way to look at the already saved > kallsyms, which keeps track of the function entry and exit to know how to > map an address back to the function. > > kallsyms_lookup(addr, NULL, &offset, NULL, NULL); > > Should give you the offset of addr from the start of the function. Good point. I should be able to overload the existing field for this purpose. Is something like the below ok? --- arch/powerpc/include/asm/ftrace.h | 13 ++++++ arch/powerpc/kernel/trace/ftrace.c | 73 ++++++++++++++++++++++++++---- kernel/trace/ftrace.c | 2 + 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index debe8c4f706260..96d6e26cee86af 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -59,6 +59,19 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) struct dyn_arch_ftrace { struct module *mod; }; + +struct dyn_ftrace; +struct module *ftrace_mod_addr_get(struct dyn_ftrace *rec); +void ftrace_mod_addr_set(struct dyn_ftrace *rec, struct module *mod); + +#ifdef CONFIG_MPROFILE_KERNEL +int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); +#define ftrace_init_nop ftrace_init_nop + +int ftrace_cmp_recs(const void *a, const void *b); +#define ftrace_cmp_recs ftrace_cmp_recs +#endif + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 80b6285769f27c..d9b6faa4c98a8c 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -428,21 +428,21 @@ int ftrace_make_nop(struct module *mod, * We should either already have a pointer to the module * or it has been passed in. */ - if (!rec->arch.mod) { + if (!ftrace_mod_addr_get(rec)) { if (!mod) { pr_err("No module loaded addr=%lx\n", addr); return -EFAULT; } - rec->arch.mod = mod; + ftrace_mod_addr_set(rec, mod); } else if (mod) { - if (mod != rec->arch.mod) { + if (mod != ftrace_mod_addr_get(rec)) { pr_err("Record mod %p not equal to passed in mod %p\n", - rec->arch.mod, mod); + ftrace_mod_addr_get(rec), mod); return -EINVAL; } /* nothing to do if mod == rec->arch.mod */ } else - mod = rec->arch.mod; + mod = ftrace_mod_addr_get(rec); return __ftrace_make_nop(mod, rec, addr); #else @@ -451,6 +451,59 @@ int ftrace_make_nop(struct module *mod, #endif /* CONFIG_MODULES */ } +#ifdef CONFIG_MPROFILE_KERNEL +struct module *ftrace_mod_addr_get(struct dyn_ftrace *rec) +{ + return (struct module *)((unsigned long)rec->arch.mod & ~0x1); +} + +void ftrace_mod_addr_set(struct dyn_ftrace *rec, struct module *mod) +{ + rec->arch.mod = (struct module *)(((unsigned long)rec->arch.mod & 0x1) | (unsigned long)mod); +} + +bool ftrace_location_has_gep(const struct dyn_ftrace *rec) +{ + return !!((unsigned long)rec->arch.mod & 0x1); +} + +int ftrace_cmp_recs(const void *a, const void *b) +{ + const struct dyn_ftrace *key = a; + const struct dyn_ftrace *rec = b; + int offset = ftrace_location_has_gep(rec) ? 12 : 4; + + if (key->flags < rec->ip - offset) + return -1; + if (key->ip >= rec->ip + MCOUNT_INSN_SIZE) + return 1; + return 0; +} + +int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) +{ + unsigned long offset; + + if (!kallsyms_lookup_size_offset(rec->ip, NULL, &offset) || (offset != 12 && offset != 4)) { + /* TODO: implement logic to deduce lep/gep from code */ + } else if (offset == 12) { + ftrace_mod_addr_set(rec, (struct module *)1); + } + + return ftrace_make_nop(mod, rec, MCOUNT_ADDR); +} +#else +struct module *ftrace_mod_addr_get(struct dyn_ftrace *rec) +{ + return rec->arch.mod; +} + +void ftrace_mod_addr_set(struct dyn_ftrace *rec, struct module * mod) +{ + rec->arch.mod = mod; +} +#endif /* CONFIG_MPROFILE_KERNEL */ + #ifdef CONFIG_MODULES #ifdef CONFIG_PPC64 /* @@ -494,7 +547,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ppc_inst_t instr; void *ip = (void *)rec->ip; unsigned long entry, ptr, tramp; - struct module *mod = rec->arch.mod; + struct module *mod = ftrace_mod_addr_get(rec); /* read where this goes */ if (copy_inst_from_kernel_nofault(op, ip)) @@ -561,7 +614,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) int err; ppc_inst_t op; u32 *ip = (u32 *)rec->ip; - struct module *mod = rec->arch.mod; + struct module *mod = ftrace_mod_addr_get(rec); unsigned long tramp; /* read where this goes */ @@ -678,7 +731,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) * Being that we are converting from nop, it had better * already have a module defined. */ - if (!rec->arch.mod) { + if (!ftrace_mod_addr_get(rec)) { pr_err("No module loaded\n"); return -EINVAL; } @@ -699,7 +752,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, ppc_inst_t op; unsigned long ip = rec->ip; unsigned long entry, ptr, tramp; - struct module *mod = rec->arch.mod; + struct module *mod = ftrace_mod_addr_get(rec); /* If we never set up ftrace trampolines, then bail */ if (!mod->arch.tramp || !mod->arch.tramp_regs) { @@ -814,7 +867,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, /* * Out of range jumps are called from modules. */ - if (!rec->arch.mod) { + if (!ftrace_mod_addr_get(rec)) { pr_err("No module loaded\n"); return -EINVAL; } diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f9feb197b2daaf..68f20cf34b0c47 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1510,6 +1510,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs) } +#ifndef ftrace_cmp_recs static int ftrace_cmp_recs(const void *a, const void *b) { const struct dyn_ftrace *key = a; @@ -1521,6 +1522,7 @@ static int ftrace_cmp_recs(const void *a, const void *b) return 1; return 0; } +#endif static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end) { Thanks, Naveen
WARNING: multiple messages have this Message-ID (diff)
From: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> To: Steven Rostedt <rostedt@goodmis.org> Cc: Daniel Borkmann <daniel@iogearbox.net>, Yauheni Kaliuta <yauheni.kaliuta@redhat.com>, Jordan Niethe <jniethe5@gmail.com>, linuxppc-dev@lists.ozlabs.org, bpf@vger.kernel.org, Jiri Olsa <jolsa@redhat.com>, Alexei Starovoitov <alexei.starovoitov@gmail.com>, Hari Bathini <hbathini@linux.ibm.com> Subject: Re: [RFC PATCH 2/3] powerpc/ftrace: Override ftrace_location_lookup() for MPROFILE_KERNEL Date: Thu, 10 Feb 2022 13:58:29 +0000 [thread overview] Message-ID: <1644501274.apfdo9z1hy.naveen@linux.ibm.com> (raw) In-Reply-To: <20220209161017.2bbdb01a@gandalf.local.home> Steven Rostedt wrote: > On Wed, 09 Feb 2022 17:50:09 +0000 > "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote: > >> However, I think we will not be able to use a fixed range. I would like >> to reserve instructions from function entry till the branch to >> _mcount(), and it can be two or four instructions depending on whether a >> function has a global entry point. For this, I am considering adding a >> field in 'struct dyn_arch_ftrace', and a hook in ftrace_process_locs() >> to initialize the same. I may need to override ftrace_cmp_recs(). > > Be careful about adding anything to dyn_arch_ftrace. powerpc already adds > the pointer to the module. Anything you add to that gets multiplied by > thousands of times (which takes up memory). > > At boot up you may see something like: > > ftrace: allocating 45363 entries in 178 pages > > That's 45,363 dyn_arch_ftrace structures. And each module loads their own > as well. To see how many total you have after boot up: > > > # cat /sys/kernel/tracing/dyn_ftrace_total_info > 55974 pages:295 groups: 89 > > That's from the same kernel. Another 10,000 entries were created by modules. > (This was for x86_64) > > What you may be able to do, is to add a way to look at the already saved > kallsyms, which keeps track of the function entry and exit to know how to > map an address back to the function. > > kallsyms_lookup(addr, NULL, &offset, NULL, NULL); > > Should give you the offset of addr from the start of the function. Good point. I should be able to overload the existing field for this purpose. Is something like the below ok? --- arch/powerpc/include/asm/ftrace.h | 13 ++++++ arch/powerpc/kernel/trace/ftrace.c | 73 ++++++++++++++++++++++++++---- kernel/trace/ftrace.c | 2 + 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index debe8c4f706260..96d6e26cee86af 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -59,6 +59,19 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) struct dyn_arch_ftrace { struct module *mod; }; + +struct dyn_ftrace; +struct module *ftrace_mod_addr_get(struct dyn_ftrace *rec); +void ftrace_mod_addr_set(struct dyn_ftrace *rec, struct module *mod); + +#ifdef CONFIG_MPROFILE_KERNEL +int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); +#define ftrace_init_nop ftrace_init_nop + +int ftrace_cmp_recs(const void *a, const void *b); +#define ftrace_cmp_recs ftrace_cmp_recs +#endif + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 80b6285769f27c..d9b6faa4c98a8c 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -428,21 +428,21 @@ int ftrace_make_nop(struct module *mod, * We should either already have a pointer to the module * or it has been passed in. */ - if (!rec->arch.mod) { + if (!ftrace_mod_addr_get(rec)) { if (!mod) { pr_err("No module loaded addr=%lx\n", addr); return -EFAULT; } - rec->arch.mod = mod; + ftrace_mod_addr_set(rec, mod); } else if (mod) { - if (mod != rec->arch.mod) { + if (mod != ftrace_mod_addr_get(rec)) { pr_err("Record mod %p not equal to passed in mod %p\n", - rec->arch.mod, mod); + ftrace_mod_addr_get(rec), mod); return -EINVAL; } /* nothing to do if mod == rec->arch.mod */ } else - mod = rec->arch.mod; + mod = ftrace_mod_addr_get(rec); return __ftrace_make_nop(mod, rec, addr); #else @@ -451,6 +451,59 @@ int ftrace_make_nop(struct module *mod, #endif /* CONFIG_MODULES */ } +#ifdef CONFIG_MPROFILE_KERNEL +struct module *ftrace_mod_addr_get(struct dyn_ftrace *rec) +{ + return (struct module *)((unsigned long)rec->arch.mod & ~0x1); +} + +void ftrace_mod_addr_set(struct dyn_ftrace *rec, struct module *mod) +{ + rec->arch.mod = (struct module *)(((unsigned long)rec->arch.mod & 0x1) | (unsigned long)mod); +} + +bool ftrace_location_has_gep(const struct dyn_ftrace *rec) +{ + return !!((unsigned long)rec->arch.mod & 0x1); +} + +int ftrace_cmp_recs(const void *a, const void *b) +{ + const struct dyn_ftrace *key = a; + const struct dyn_ftrace *rec = b; + int offset = ftrace_location_has_gep(rec) ? 12 : 4; + + if (key->flags < rec->ip - offset) + return -1; + if (key->ip >= rec->ip + MCOUNT_INSN_SIZE) + return 1; + return 0; +} + +int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) +{ + unsigned long offset; + + if (!kallsyms_lookup_size_offset(rec->ip, NULL, &offset) || (offset != 12 && offset != 4)) { + /* TODO: implement logic to deduce lep/gep from code */ + } else if (offset == 12) { + ftrace_mod_addr_set(rec, (struct module *)1); + } + + return ftrace_make_nop(mod, rec, MCOUNT_ADDR); +} +#else +struct module *ftrace_mod_addr_get(struct dyn_ftrace *rec) +{ + return rec->arch.mod; +} + +void ftrace_mod_addr_set(struct dyn_ftrace *rec, struct module * mod) +{ + rec->arch.mod = mod; +} +#endif /* CONFIG_MPROFILE_KERNEL */ + #ifdef CONFIG_MODULES #ifdef CONFIG_PPC64 /* @@ -494,7 +547,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ppc_inst_t instr; void *ip = (void *)rec->ip; unsigned long entry, ptr, tramp; - struct module *mod = rec->arch.mod; + struct module *mod = ftrace_mod_addr_get(rec); /* read where this goes */ if (copy_inst_from_kernel_nofault(op, ip)) @@ -561,7 +614,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) int err; ppc_inst_t op; u32 *ip = (u32 *)rec->ip; - struct module *mod = rec->arch.mod; + struct module *mod = ftrace_mod_addr_get(rec); unsigned long tramp; /* read where this goes */ @@ -678,7 +731,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) * Being that we are converting from nop, it had better * already have a module defined. */ - if (!rec->arch.mod) { + if (!ftrace_mod_addr_get(rec)) { pr_err("No module loaded\n"); return -EINVAL; } @@ -699,7 +752,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, ppc_inst_t op; unsigned long ip = rec->ip; unsigned long entry, ptr, tramp; - struct module *mod = rec->arch.mod; + struct module *mod = ftrace_mod_addr_get(rec); /* If we never set up ftrace trampolines, then bail */ if (!mod->arch.tramp || !mod->arch.tramp_regs) { @@ -814,7 +867,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, /* * Out of range jumps are called from modules. */ - if (!rec->arch.mod) { + if (!ftrace_mod_addr_get(rec)) { pr_err("No module loaded\n"); return -EINVAL; } diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f9feb197b2daaf..68f20cf34b0c47 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1510,6 +1510,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs) } +#ifndef ftrace_cmp_recs static int ftrace_cmp_recs(const void *a, const void *b) { const struct dyn_ftrace *key = a; @@ -1521,6 +1522,7 @@ static int ftrace_cmp_recs(const void *a, const void *b) return 1; return 0; } +#endif static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end) { Thanks, Naveen
next prev parent reply other threads:[~2022-02-10 13:59 UTC|newest] Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-02-07 7:07 [RFC PATCH 0/3] powerpc64/bpf: Add support for BPF Trampolines Naveen N. Rao 2022-02-07 7:07 ` Naveen N. Rao 2022-02-07 7:07 ` [RFC PATCH 1/3] ftrace: Add ftrace_location_lookup() to lookup address of ftrace location Naveen N. Rao 2022-02-07 7:07 ` Naveen N. Rao 2022-02-07 7:07 ` [RFC PATCH 2/3] powerpc/ftrace: Override ftrace_location_lookup() for MPROFILE_KERNEL Naveen N. Rao 2022-02-07 7:07 ` Naveen N. Rao 2022-02-07 15:24 ` Steven Rostedt 2022-02-07 15:24 ` Steven Rostedt 2022-02-09 17:50 ` Naveen N. Rao 2022-02-09 17:50 ` Naveen N. Rao 2022-02-09 21:10 ` Steven Rostedt 2022-02-09 21:10 ` Steven Rostedt 2022-02-10 13:58 ` Naveen N. Rao [this message] 2022-02-10 13:58 ` Naveen N. Rao 2022-02-10 14:59 ` Steven Rostedt 2022-02-10 14:59 ` Steven Rostedt 2022-02-10 16:40 ` Naveen N. Rao 2022-02-10 16:40 ` Naveen N. Rao 2022-02-10 17:01 ` Steven Rostedt 2022-02-10 17:01 ` Steven Rostedt 2022-02-11 11:36 ` Naveen N. Rao 2022-02-11 11:36 ` Naveen N. Rao 2022-02-07 7:07 ` [RFC PATCH 3/3] powerpc64/bpf: Add support for bpf trampolines Naveen N. Rao 2022-02-07 7:07 ` Naveen N. Rao 2022-02-11 14:40 ` [RFC PATCH 0/3] powerpc64/bpf: Add support for BPF Trampolines Christophe Leroy 2022-02-11 14:40 ` Christophe Leroy 2022-02-14 10:47 ` Naveen N. Rao 2022-02-14 10:47 ` 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=1644501274.apfdo9z1hy.naveen@linux.ibm.com \ --to=naveen.n.rao@linux.vnet.ibm.com \ --cc=alexei.starovoitov@gmail.com \ --cc=bpf@vger.kernel.org \ --cc=daniel@iogearbox.net \ --cc=hbathini@linux.ibm.com \ --cc=jniethe5@gmail.com \ --cc=jolsa@redhat.com \ --cc=linuxppc-dev@lists.ozlabs.org \ --cc=mpe@ellerman.id.au \ --cc=rostedt@goodmis.org \ --cc=yauheni.kaliuta@redhat.com \ /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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.