public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
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



  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