From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
To: Wang Nan <wangnan0@huawei.com>
Cc: pmladek@suse.cz, lizefan@huawei.com,
linux-kernel@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org
Subject: Re: Re: [PATCH 3/3] early kprobes: x86: don't try to recover ftraced instruction before ftrace get ready.
Date: Thu, 05 Mar 2015 00:26:48 +0900 [thread overview]
Message-ID: <54F72438.3010405@hitachi.com> (raw)
In-Reply-To: <1425468122-54515-1-git-send-email-wangnan0@huawei.com>
Hi Wang,
(2015/03/04 20:22), Wang Nan wrote:
> Hi Masami,
>
> Following your advise, I adjusted early kprobe patches, added a
> kprobes_init_stage var to indicate the initiaization progress of
> kprobes. It has following avaliable values:
>
> typedef enum {
> /* kprobe initialization is error. */
> KP_STG_ERR = -1,
Eventually, all the negative values should be handled as an error,
then we can store an encoded error reason or location on it.
Anyway, at this point we don't need it.
> /* kprobe is not ready. */
> KP_STG_NONE,
Please put the comment on the same line, as below.
KP_STG_ERR = -1, /* kprobe initialization is error. */
KP_STG_NONE, /* kprobe is not ready. */
...
> /* kprobe is available. */
> KP_STG_AVAIL,
KP_STG_EARLY is better, isn't it? :)
> /* Ftrace initialize is ready */
> KP_STG_FTRACE_READY,
> /* All resources are ready */
> KP_STG_FULL,
> /*
> * Since memory system is ready before ftrace, after ftrace inited we
> * are able to alloc normal kprobes.
> */
> #define KP_STG_NORMAL KP_STG_FTRACE_READY
No need to use macro, you can directly define enum symbol.
KP_STG_NORMAL = KP_STG_FTRACE_READY
BTW, what's the difference of FULL and NORMAL?
> } kprobes_init_stage_t;
>
> And kprobes_is_early becomes:
>
> static inline bool kprobes_is_early(void)
> {
> return (kprobes_init_stage < KP_STG_NORMAL);
> }
>
> A helper function is add to make progress:
>
> static void kprobes_update_init_stage(kprobes_init_stage_t s)
> {
> BUG_ON((kprobes_init_stage == KP_STG_ERR) ||
> ((s <= kprobes_init_stage) && (s != KP_STG_ERR)));
> kprobes_init_stage = s;
> }
Good! this serializes the initialization stage :)
>
> Original kprobes_initialized, kprobes_blacklist_initialized
> kprobes_on_ftrace_initialized are all removed, replaced by:
>
> kprobes_initialized --> (kprobes_init_stage >= KP_STG_AVAIL)
> kprobes_blacklist_initialized --> (kprobes_init_stage >= KP_STG_FULL)
> kprobes_on_ftrace_initialized --> (kprobes_init_stage >= KP_STG_FTRACE_READY)
>
> respectively.
Yes, that is what I want.
>
> Following patch is extracted from my WIP v5 series and will be distributed
> into separated patches.
>
> (Please note that it is edited manually and unable to be applied directly.)
>
> Do you have any futher suggestion?
Sorry, I have still not reviewed your series yet, but it seems that your
patches are chopped to smaller pieces. I recommend you to fold them up to
better granularity, like
- Each patch can be compiled without warnings.
- If you introduce new functions, it should be called from somewhere in
the same patch. (no orphaned functions, except for module APIs)
- Bugfix, cleanup, and enhance it.
And now I'm considering that the early kprobe should be started as an
independent series from ftrace. For example, we can configure early_kprobe
only when KPROBE_ON_FTRACE=n. That will make it simpler and we can focus
on what we basically need to do.
Thank you,
>
> Thank you!
>
> ---
> diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
> index 87beb64..f8b7dcb 100644
> --- a/arch/x86/kernel/kprobes/core.c
> +++ b/arch/x86/kernel/kprobes/core.c
> @@ -234,6 +234,20 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
> */
> if (WARN_ON(faddr && faddr != addr))
> return 0UL;
> +
> + /*
> + * If ftrace is not ready yet, pretend this is not an ftrace
> + * location, because currently the target instruction has not
> + * been replaced by a NOP yet. When ftrace trying to convert
> + * it to NOP, kprobe should be notified and the kprobe data
> + * should be fixed at that time.
> + *
> + * Since it is possible that an early kprobe already on that
> + * place, don't return addr directly.
> + */
> + if (unlikely(kprobes_init_stage < KP_STG_FTRACE_READY))
> + faddr = 0UL;
> +
> /*
> * Use the current code if it is not modified by Kprobe
> * and it cannot be modified by ftrace.
> diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
> index 2d78bbb..04b97ec 100644
> --- a/include/linux/kprobes.h
> +++ b/include/linux/kprobes.h
> @@ -50,7 +50,31 @@
> #define KPROBE_REENTER 0x00000004
> #define KPROBE_HIT_SSDONE 0x00000008
>
> -extern bool kprobes_is_early(void);
> +/* Initialization state of kprobe */
> +typedef enum {
> + /* kprobe initialization is error. */
> + KP_STG_ERR = -1,
> + /* kprobe is not ready. */
> + KP_STG_NONE,
> + /* kprobe is available. */
> + KP_STG_AVAIL,
> + /* Ftrace initialize is ready */
> + KP_STG_FTRACE_READY,
> + /* All resources are ready */
> + KP_STG_FULL,
> +/*
> + * Since memory system is ready before ftrace, after ftrace inited we
> + * are able to alloc normal kprobes.
> + */
> +#define KP_STG_NORMAL KP_STG_FTRACE_READY
> +} kprobes_init_stage_t;
> +
> +extern kprobes_init_stage_t kprobes_init_stage;
> +
> +static inline bool kprobes_is_early(void)
> +{
> + return (kprobes_init_stage < KP_STG_NORMAL);
> +}
>
> #else /* CONFIG_KPROBES */
> typedef int kprobe_opcode_t;
> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> index 1ec8e6e..f4d9fca 100644
> --- a/kernel/kprobes.c
> +++ b/kernel/kprobes.c
> @@ -67,17 +67,14 @@
> addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
> #endif
>
> -static int kprobes_initialized;
> -static int kprobes_blacklist_initialized;
> -#if defined(CONFIG_KPROBES_ON_FTRACE) && defined(CONFIG_EARLY_KPROBES)
> -static bool kprobes_on_ftrace_initialized __read_mostly = false;
> -#else
> -# define kprobes_on_ftrace_initialized false
> -#endif
> +kprobes_init_stage_t kprobes_init_stage __read_mostly = KP_STG_NONE;
> +#define kprobes_initialized (kprobes_init_stage >= KP_STG_AVAIL)
>
> -bool kprobes_is_early(void)
> +static void kprobes_update_init_stage(kprobes_init_stage_t s)
> {
> - return !(kprobes_initialized && kprobes_blacklist_initialized);
> + BUG_ON((kprobes_init_stage == KP_STG_ERR) ||
> + ((s <= kprobes_init_stage) && (s != KP_STG_ERR)));
> + kprobes_init_stage = s;
> }
>
> static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
> @@ -1416,7 +1415,7 @@ static bool within_kprobe_blacklist(unsigned long addr)
> return true;
> #endif
>
> - if (!kprobes_blacklist_initialized)
> + if (kprobes_init_stage < KP_STG_FULL)
> return within_kprobe_blacklist_early(addr);
>
> /*
> @@ -1502,7 +1501,7 @@ int __weak arch_check_ftrace_location(struct kprobe *p)
> /* Given address is not on the instruction boundary */
> if ((unsigned long)p->addr != ftrace_addr)
> return -EILSEQ;
> - if (unlikely(!kprobes_on_ftrace_initialized))
> + if (unlikely(kprobes_init_stage < KP_STG_FTRACE_READY))
> p->flags |= KPROBE_FLAG_FTRACE_EARLY;
> else
> p->flags |= KPROBE_FLAG_FTRACE;
> @@ -1569,10 +1568,8 @@ int register_kprobe(struct kprobe *p)
> struct module *probed_mod;
> kprobe_opcode_t *addr;
>
> -#ifndef CONFIG_EARLY_KPROBES
> - if (kprobes_is_early())
> - return -EAGAIN;
> -#endif
> + if (kprobes_init_stage < KP_STG_AVAIL)
> + return -ENOSYS;
>
> /* Adjust probe address from symbol */
> addr = kprobe_addr(p);
> @@ -2271,7 +2286,8 @@ void init_kprobes_early(void)
> if (!err)
> err = register_module_notifier(&kprobe_module_nb);
>
> - kprobes_initialized = (err == 0);
> + kprobes_update_init_stage(err == 0 ? KP_STG_AVAIL : KP_STG_ERR);
> +
> #ifdef CONFIG_EARLY_KPROBES
> if (!err)
> init_test_probes();
> @@ -2301,9 +2317,7 @@ static int __init init_kprobes(void)
> pr_err("kprobes: failed to populate blacklist: %d\n", err);
> pr_err("Please take care of using kprobes.\n");
> }
> - kprobes_blacklist_initialized = (err == 0);
> -
> - err = kprobes_is_early() ? -ENOSYS : 0;
> + kprobes_update_init_stage(err == 0 ? KP_STG_FULL : KP_STG_ERR);
>
> /* TODO: deal with early kprobes. */
>
> @@ -2607,7 +2621,7 @@ bool kprobe_fix_ftrace_make_nop(struct dyn_ftrace *rec)
> int optimized;
> void *addr;
>
> - if (kprobes_on_ftrace_initialized)
> + if (kprobes_init_stage >= KP_STG_FTRACE_READY)
> return false;
>
> addr = (void *)rec->ip;
> @@ -2731,15 +2745,20 @@ static void convert_early_kprobes_on_ftrace(void)
> }
> }
> }
> - mutex_unlock(&kprobe_mutex);
> }
> +#else
> +static inline void convert_early_kprobes_on_ftrace(void)
> +{
> +}
> +#endif // CONFIG_KPROBES_ON_FTRACE && CONFIG_EARLY_KPROBES
>
> void init_kprobes_on_ftrace(void)
> {
> - kprobes_on_ftrace_initialized = true;
> + mutex_lock(&kprobe_mutex);
> + kprobes_update_init_stage(KP_STG_FTRACE_READY);
> convert_early_kprobes_on_ftrace();
> + mutex_unlock(&kprobe_mutex);
> }
> -#endif
>
> #ifdef CONFIG_EARLY_KPROBES
> static int early_kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs)
>
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
next prev parent reply other threads:[~2015-03-04 15:26 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-02 14:24 [RFC PATCH v4 00/34] Early kprobe: enable kprobes at very early booting stage Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 01/34] x86, traps: Enable DEBUG_STACK after cpu_init() for TRAP_DB/BP Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 02/34] x86, traps: separate set_intr_gate() and cleanup early_trap_init() Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 03/34] x86, traps: install gates using IST after cpu_init() Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 04/34] early kprobes: within_kprobe_blacklist_early() early Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 05/34] early kprobes: introduce kprobe_is_early for futher early kprobe use Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 06/34] early kprobes: enable kprobe smoke test for early kprobes Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 07/34] early kprobes: init kprobes at very early stage Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 08/34] early kprobes: ARM: add definition for vmlinux.lds use Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 09/34] early kprobes: x86: " Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 10/34] early kprobes: introduce early kprobes related code area Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 11/34] early kprobes: introduces macros for allocing early kprobe resources Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 12/34] early kprobes: allows __alloc_insn_slot() from early kprobes slots Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 13/34] early kprobes: alloc optimized kprobe before memory system is ready Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 14/34] early kprobes: use stop_machine() based x86 optimizer Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 15/34] early kprobes: use stop_machine() based optimization method for early kprobes Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 16/34] early kprobes: perhibit probing at early kprobe reserved area Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 17/34] early kprobes: run kprobes smoke test for early kprobes Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 18/34] early kprobes: add CONFIG_EARLY_KPROBES option Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 19/34] ftrace: don't update record flags if code modification fail Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 20/34] ftrace/x86: Ensure rec->flags no change when failure occures Wang Nan
2015-03-02 14:24 ` [RFC PATCH v4 21/34] ftrace: sort ftrace entries earlier Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 22/34] ftrace: allow search ftrace addr before ftrace fully inited Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 23/34] ftrace: notify kprobe when ftrace is initialized Wang Nan
2015-03-03 16:29 ` Petr Mladek
2015-03-02 14:25 ` [RFC PATCH v4 24/34] early kprobes on ftrace: introduce x86 arch_fix_ftrace_early_kprobe() Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 25/34] ftrace: don't fire ftrace_bug if the instruction is taken by early kprobes Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 26/34] early kprobes on ftrace: x86: arch code for retrieving kprobed instruction Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 27/34] early kprobes on ftrace: kprobe_on_ftrace_get_old_insn() Wang Nan
2015-03-04 2:30 ` Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 28/34] ftrace: x86: get old instruction from early kprobes when make call Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 29/34] ftrace: x86: call kprobe_int3_handler() in ftrace int3 handler Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 30/34] early kprobes: convert early kprobes on ftrace to ftrace Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 31/34] early kprobes: enable early kprobes for x86 Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 32/34] early kprobes: enable 'ekprobe=' cmdline option for early kprobes Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 33/34] ftrace: enable make ftrace nop before ftrace_init() Wang Nan
2015-03-02 14:25 ` [RFC PATCH v4 34/34] early kprobes: enable optimization of kprobes on ftrace before ftrace is ready Wang Nan
2015-03-03 5:09 ` [PATCH 0/3] early kprobes: Fix bug in unregistering early kprobe before kprobe " Wang Nan
2015-03-03 5:09 ` [PATCH 1/3] early kprobes: make kprobes_on_ftrace_initialized public available Wang Nan
2015-03-03 5:09 ` [PATCH 2/3] ftrace/x86: don't return error if other makes a same code change Wang Nan
2015-03-03 5:09 ` [PATCH 3/3] early kprobes: x86: don't try to recover ftraced instruction before ftrace get ready Wang Nan
2015-03-03 17:06 ` Petr Mladek
2015-03-04 2:24 ` Wang Nan
2015-03-04 3:36 ` Masami Hiramatsu
2015-03-04 4:39 ` Wang Nan
2015-03-04 5:59 ` Masami Hiramatsu
2015-03-04 11:22 ` Wang Nan
2015-03-04 15:26 ` Masami Hiramatsu [this message]
2015-03-05 1:53 ` Wang Nan
2015-03-05 2:06 ` Wang Nan
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=54F72438.3010405@hitachi.com \
--to=masami.hiramatsu.pt@hitachi.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan@huawei.com \
--cc=pmladek@suse.cz \
--cc=wangnan0@huawei.com \
--cc=x86@kernel.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