All of lore.kernel.org
 help / color / mirror / Atom feed
From: liuj97@gmail.com (Jiang Liu)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v1 2/7] arm64: introduce interfaces to hotpatch kernel and module code
Date: Wed, 25 Sep 2013 23:54:52 +0800	[thread overview]
Message-ID: <5243074C.5000507@gmail.com> (raw)
In-Reply-To: <CA+b37P2McAMq80jppqoD58QjhrJ7f2cEX4JJdivVfuRH1-69VQ@mail.gmail.com>

Hi Sandeepa,
	Great to know that you are working on kprobe for ARM64.
I have done some investigation, found it's an huge work for me
then gave up:(
	I will try refine the implementation based on your requirement.
	Thanks!

On 09/25/2013 10:35 PM, Sandeepa Prabhu wrote:
> On 25 September 2013 16:14, Jiang Liu <liuj97@gmail.com> wrote:
>> From: Jiang Liu <jiang.liu@huawei.com>
>>
>> Introduce aarch64_insn_patch_text() and __aarch64_insn_patch_text()
>> to patch kernel and module code.
>>
>> Function aarch64_insn_patch_text() is a heavy version which may use
>> stop_machine() to serialize all online CPUs, and function
>> __aarch64_insn_patch_text() is light version without explicitly
>> serialization.
> Hi Jiang,
> 
> I have written kprobes support for aarch64, and need both the
> functionality (lightweight and stop_machine() versions).
> I would like to rebase these API in kprobes, however slight changes
> would require in case of stop_machine version, which I explained
> below.
> [Though kprobes cannot share Instruction encode support of jump labels
> as, decoding & simulation quite different for kprobes/uprobes and
> based around single stepping]
> 
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> Cc: Jiang Liu <liuj97@gmail.com>
>> ---
>>  arch/arm64/include/asm/insn.h |  2 ++
>>  arch/arm64/kernel/insn.c      | 64 +++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 66 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
>> index e7d1bc8..0ea7193 100644
>> --- a/arch/arm64/include/asm/insn.h
>> +++ b/arch/arm64/include/asm/insn.h
>> @@ -49,5 +49,7 @@ __AARCH64_INSN_FUNCS(nop,     0xFFFFFFFF, 0xD503201F)
>>  enum aarch64_insn_class aarch64_get_insn_class(u32 insn);
>>
>>  bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
>> +int aarch64_insn_patch_text(void *addr, u32 *insns, int cnt);
>> +int __aarch64_insn_patch_text(void *addr, u32 *insns, int cnt);
>>
>>  #endif /* _ASM_ARM64_INSN_H */
>> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
>> index 8541c3a..50facfc 100644
>> --- a/arch/arm64/kernel/insn.c
>> +++ b/arch/arm64/kernel/insn.c
>> @@ -15,6 +15,8 @@
>>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>   */
>>  #include <linux/kernel.h>
>> +#include <linux/stop_machine.h>
>> +#include <asm/cacheflush.h>
>>  #include <asm/insn.h>
>>
>>  static int aarch64_insn_cls[] = {
>> @@ -69,3 +71,65 @@ bool __kprobes aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn)
>>         return __aarch64_insn_hotpatch_safe(old_insn) &&
>>                __aarch64_insn_hotpatch_safe(new_insn);
>>  }
>> +
>> +struct aarch64_insn_patch {
>> +       void    *text_addr;
>> +       u32     *new_insns;
>> +       int     insn_cnt;
>> +};
>> +
>> +int __kprobes __aarch64_insn_patch_text(void *addr, u32 *insns, int cnt)
>> +{
>> +       int i;
>> +       u32 *tp = addr;
>> +
>> +       /* instructions must be word aligned */
>> +       if (cnt <= 0 || ((uintptr_t)addr & 0x3))
>> +               return -EINVAL;
>> +
>> +       for (i = 0; i < cnt; i++)
>> +               tp[i] = insns[i];
>> +
>> +       flush_icache_range((uintptr_t)tp, (uintptr_t)tp + cnt * sizeof(u32));
>> +
>> +       return 0;
>> +}
> Looks fine, but do you need to check for CPU big endian mode here? (I
> think swab32() needed if EL1 is in big-endian mode)
> 
>> +
>> +static int __kprobes aarch64_insn_patch_text_cb(void *arg)
>> +{
>> +       struct aarch64_insn_patch *pp = arg;
>> +
>> +       return __aarch64_insn_patch_text(pp->text_addr, pp->new_insns,
>> +                                        pp->insn_cnt);
>> +}
>> +
>> +int __kprobes aarch64_insn_patch_text(void *addr, u32 *insns, int cnt)
>> +{
>> +       int ret;
>> +       bool safe = false;
>> +
>> +       /* instructions must be word aligned */
>> +       if (cnt <= 0 || ((uintptr_t)addr & 0x3))
>> +               return -EINVAL;
>> +
>> +       if (cnt == 1)
>> +               safe = aarch64_insn_hotpatch_safe(*(u32 *)addr, insns[0]);
>> +
>> +       if (safe) {
>> +               ret = __aarch64_insn_patch_text(addr, insns, cnt);
>> +       } else {
> 
> Can you move the code below this into separate API that just apply
> patch with stop_machine? And then a wrapper function for jump label
> specific handling that checks for aarch64_insn_hotpatch_safe() ?
> Also, it will be good to move the patching code out of insn.c to
> patch.c (refer to arch/arm/kernel/patch.c).
> 
> Please refer to attached file (my current implementation) to make
> sense of exactly what kprobes would need (ignore the big-endian part
> for now). I think splitting the code should be straight-forward and we
> can avoid two different implementations. Please let me know if this
> can be done, I will rebase my patches above your next version.
> 
> Thanks,
> Sandeepa
>> +               struct aarch64_insn_patch patch = {
>> +                       .text_addr = addr,
>> +                       .new_insns = insns,
>> +                       .insn_cnt = cnt,
>> +               };
>> +
>> +               /*
>> +                * Execute __aarch64_insn_patch_text() on every online CPU,
>> +                * which ensure serialization among all online CPUs.
>> +                */
>> +               ret = stop_machine(aarch64_insn_patch_text_cb, &patch, NULL);
>> +       }
>> +
>> +       return ret;
>> +}
>> --
>> 1.8.1.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/

WARNING: multiple messages have this Message-ID (diff)
From: Jiang Liu <liuj97@gmail.com>
To: Sandeepa Prabhu <sandeepa.prabhu@linaro.org>
Cc: Steven Rostedt <rostedt@goodmis.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will.deacon@arm.com>,
	Jiang Liu <jiang.liu@huawei.com>,
	"linux-arm-kernel@lists.infradead.org" 
	<linux-arm-kernel@lists.infradead.org>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 2/7] arm64: introduce interfaces to hotpatch kernel and module code
Date: Wed, 25 Sep 2013 23:54:52 +0800	[thread overview]
Message-ID: <5243074C.5000507@gmail.com> (raw)
In-Reply-To: <CA+b37P2McAMq80jppqoD58QjhrJ7f2cEX4JJdivVfuRH1-69VQ@mail.gmail.com>

Hi Sandeepa,
	Great to know that you are working on kprobe for ARM64.
I have done some investigation, found it's an huge work for me
then gave up:(
	I will try refine the implementation based on your requirement.
	Thanks!

On 09/25/2013 10:35 PM, Sandeepa Prabhu wrote:
> On 25 September 2013 16:14, Jiang Liu <liuj97@gmail.com> wrote:
>> From: Jiang Liu <jiang.liu@huawei.com>
>>
>> Introduce aarch64_insn_patch_text() and __aarch64_insn_patch_text()
>> to patch kernel and module code.
>>
>> Function aarch64_insn_patch_text() is a heavy version which may use
>> stop_machine() to serialize all online CPUs, and function
>> __aarch64_insn_patch_text() is light version without explicitly
>> serialization.
> Hi Jiang,
> 
> I have written kprobes support for aarch64, and need both the
> functionality (lightweight and stop_machine() versions).
> I would like to rebase these API in kprobes, however slight changes
> would require in case of stop_machine version, which I explained
> below.
> [Though kprobes cannot share Instruction encode support of jump labels
> as, decoding & simulation quite different for kprobes/uprobes and
> based around single stepping]
> 
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> Cc: Jiang Liu <liuj97@gmail.com>
>> ---
>>  arch/arm64/include/asm/insn.h |  2 ++
>>  arch/arm64/kernel/insn.c      | 64 +++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 66 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
>> index e7d1bc8..0ea7193 100644
>> --- a/arch/arm64/include/asm/insn.h
>> +++ b/arch/arm64/include/asm/insn.h
>> @@ -49,5 +49,7 @@ __AARCH64_INSN_FUNCS(nop,     0xFFFFFFFF, 0xD503201F)
>>  enum aarch64_insn_class aarch64_get_insn_class(u32 insn);
>>
>>  bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
>> +int aarch64_insn_patch_text(void *addr, u32 *insns, int cnt);
>> +int __aarch64_insn_patch_text(void *addr, u32 *insns, int cnt);
>>
>>  #endif /* _ASM_ARM64_INSN_H */
>> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
>> index 8541c3a..50facfc 100644
>> --- a/arch/arm64/kernel/insn.c
>> +++ b/arch/arm64/kernel/insn.c
>> @@ -15,6 +15,8 @@
>>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>   */
>>  #include <linux/kernel.h>
>> +#include <linux/stop_machine.h>
>> +#include <asm/cacheflush.h>
>>  #include <asm/insn.h>
>>
>>  static int aarch64_insn_cls[] = {
>> @@ -69,3 +71,65 @@ bool __kprobes aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn)
>>         return __aarch64_insn_hotpatch_safe(old_insn) &&
>>                __aarch64_insn_hotpatch_safe(new_insn);
>>  }
>> +
>> +struct aarch64_insn_patch {
>> +       void    *text_addr;
>> +       u32     *new_insns;
>> +       int     insn_cnt;
>> +};
>> +
>> +int __kprobes __aarch64_insn_patch_text(void *addr, u32 *insns, int cnt)
>> +{
>> +       int i;
>> +       u32 *tp = addr;
>> +
>> +       /* instructions must be word aligned */
>> +       if (cnt <= 0 || ((uintptr_t)addr & 0x3))
>> +               return -EINVAL;
>> +
>> +       for (i = 0; i < cnt; i++)
>> +               tp[i] = insns[i];
>> +
>> +       flush_icache_range((uintptr_t)tp, (uintptr_t)tp + cnt * sizeof(u32));
>> +
>> +       return 0;
>> +}
> Looks fine, but do you need to check for CPU big endian mode here? (I
> think swab32() needed if EL1 is in big-endian mode)
> 
>> +
>> +static int __kprobes aarch64_insn_patch_text_cb(void *arg)
>> +{
>> +       struct aarch64_insn_patch *pp = arg;
>> +
>> +       return __aarch64_insn_patch_text(pp->text_addr, pp->new_insns,
>> +                                        pp->insn_cnt);
>> +}
>> +
>> +int __kprobes aarch64_insn_patch_text(void *addr, u32 *insns, int cnt)
>> +{
>> +       int ret;
>> +       bool safe = false;
>> +
>> +       /* instructions must be word aligned */
>> +       if (cnt <= 0 || ((uintptr_t)addr & 0x3))
>> +               return -EINVAL;
>> +
>> +       if (cnt == 1)
>> +               safe = aarch64_insn_hotpatch_safe(*(u32 *)addr, insns[0]);
>> +
>> +       if (safe) {
>> +               ret = __aarch64_insn_patch_text(addr, insns, cnt);
>> +       } else {
> 
> Can you move the code below this into separate API that just apply
> patch with stop_machine? And then a wrapper function for jump label
> specific handling that checks for aarch64_insn_hotpatch_safe() ?
> Also, it will be good to move the patching code out of insn.c to
> patch.c (refer to arch/arm/kernel/patch.c).
> 
> Please refer to attached file (my current implementation) to make
> sense of exactly what kprobes would need (ignore the big-endian part
> for now). I think splitting the code should be straight-forward and we
> can avoid two different implementations. Please let me know if this
> can be done, I will rebase my patches above your next version.
> 
> Thanks,
> Sandeepa
>> +               struct aarch64_insn_patch patch = {
>> +                       .text_addr = addr,
>> +                       .new_insns = insns,
>> +                       .insn_cnt = cnt,
>> +               };
>> +
>> +               /*
>> +                * Execute __aarch64_insn_patch_text() on every online CPU,
>> +                * which ensure serialization among all online CPUs.
>> +                */
>> +               ret = stop_machine(aarch64_insn_patch_text_cb, &patch, NULL);
>> +       }
>> +
>> +       return ret;
>> +}
>> --
>> 1.8.1.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/


  reply	other threads:[~2013-09-25 15:54 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-25 10:44 [PATCH v1 0/7] Optimize jump label implementation on ARM64 Jiang Liu
2013-09-25 10:44 ` Jiang Liu
2013-09-25 10:44 ` [PATCH v1 1/7] arm64: introduce basic aarch64 instruction decoding helpers Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 12:58   ` Christopher Covington
2013-09-25 12:58     ` Christopher Covington
2013-09-25 15:50     ` Jiang Liu
2013-09-25 15:50       ` Jiang Liu
2013-09-25 10:44 ` [PATCH v1 2/7] arm64: introduce interfaces to hotpatch kernel and module code Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 14:35   ` Steven Rostedt
2013-09-25 14:35     ` Steven Rostedt
2013-09-25 14:42     ` Sandeepa Prabhu
2013-09-25 14:42       ` Sandeepa Prabhu
2013-09-25 15:16       ` Steven Rostedt
2013-09-25 15:16         ` Steven Rostedt
2013-09-26  2:47         ` Sandeepa Prabhu
2013-09-26  2:47           ` Sandeepa Prabhu
2013-09-25 14:35   ` Sandeepa Prabhu
2013-09-25 14:35     ` Sandeepa Prabhu
2013-09-25 15:54     ` Jiang Liu [this message]
2013-09-25 15:54       ` Jiang Liu
2013-09-26  2:51       ` Sandeepa Prabhu
2013-09-26  2:51         ` Sandeepa Prabhu
2013-09-27 15:41     ` Jiang Liu
2013-09-27 15:41       ` Jiang Liu
2013-09-28  1:22       ` Sandeepa Prabhu
2013-09-28  1:22         ` Sandeepa Prabhu
2013-09-25 10:44 ` [PATCH v1 3/7] arm64: move encode_insn_immediate() from module.c to insn.c Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 10:44 ` [PATCH v1 4/7] arm64: introduce aarch64_insn_gen_{nop|branch_imm}() helper functions Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 10:44 ` [PATCH v1 5/7] arm64, jump label: detect %c support for ARM64 Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 10:44 ` [PATCH v1 6/7] arm64, jump label: optimize jump label implementation Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 10:44 ` [PATCH v1 7/7] jump_label: use defined macros instead of hard-coding for better readability Jiang Liu
2013-09-25 10:44   ` Jiang Liu
2013-09-25 14:53   ` Steven Rostedt
2013-09-25 14:53     ` Steven Rostedt
2013-09-25 15:47     ` Jiang Liu
2013-09-25 15:47       ` Jiang Liu
2013-09-25 16:30       ` Steven Rostedt
2013-09-25 16:30         ` Steven Rostedt

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=5243074C.5000507@gmail.com \
    --to=liuj97@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.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 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.