public inbox for linux-riscv@lists.infradead.org
 help / color / mirror / Atom feed
From: Ben Dooks <ben.dooks@codethink.co.uk>
To: felix.chong@codethink.co.uk, lawrence.hunter@codethink.co.uk,
	roan.richmond@codethink.co.uk, linux-riscv@lists.infradead.org
Cc: Ben Dooks <ben.dooks@codethink.co.uk>
Subject: [RFC 13/15] riscv: probes: sort out endian-ness
Date: Fri, 20 Dec 2024 15:57:59 +0000	[thread overview]
Message-ID: <20241220155801.1988785-14-ben.dooks@codethink.co.uk> (raw)
In-Reply-To: <20241220155801.1988785-1-ben.dooks@codethink.co.uk>

Updated {k,u}probe code to deal with big endian mode where
the instruction stream is always in little endian.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
---
 arch/riscv/kernel/probes/decode-insn.c |  2 +-
 arch/riscv/kernel/probes/decode-insn.h |  5 +++++
 arch/riscv/kernel/probes/kprobes.c     | 30 ++++++++++++++++----------
 arch/riscv/kernel/probes/uprobes.c     | 10 ++++-----
 4 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 65d9590bfb9f..5f30c10f7d8d 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -16,7 +16,7 @@
 enum probe_insn __kprobes
 riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
 {
-	probe_opcode_t insn = *addr;
+	probe_opcode_t insn = le32_to_cpu(*addr);
 
 	/*
 	 * Reject instructions list:
diff --git a/arch/riscv/kernel/probes/decode-insn.h b/arch/riscv/kernel/probes/decode-insn.h
index 42269a7d676d..0515deb204b5 100644
--- a/arch/riscv/kernel/probes/decode-insn.h
+++ b/arch/riscv/kernel/probes/decode-insn.h
@@ -15,4 +15,9 @@ enum probe_insn {
 enum probe_insn __kprobes
 riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *asi);
 
+static inline int read_insn_length(void *ptr)
+{
+	return GET_INSN_LENGTH(le16_to_cpu(*(__le16 *)ptr));
+}
+
 #endif /* _RISCV_KERNEL_KPROBES_DECODE_INSN_H */
diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
index 474a65213657..aba684938284 100644
--- a/arch/riscv/kernel/probes/kprobes.c
+++ b/arch/riscv/kernel/probes/kprobes.c
@@ -24,13 +24,13 @@ post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
 
 static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
 {
-	size_t len = GET_INSN_LENGTH(p->opcode);
-	u32 insn = __BUG_INSN_32;
+	size_t len = read_insn_length(&p->opcode);
+	u32 insn = cpu_to_le32(__BUG_INSN_32);
 
 	p->ainsn.api.restore = (unsigned long)p->addr + len;
 
 	patch_text_nosync(p->ainsn.api.insn, &p->opcode, len);
-	patch_text_nosync(p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(insn));
+	patch_text_nosync((void *)p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(__BUG_INSN_32));
 }
 
 static void __kprobes arch_prepare_simulate(struct kprobe *p)
@@ -58,7 +58,7 @@ static bool __kprobes arch_check_kprobe(struct kprobe *p)
 		if (tmp == addr)
 			return true;
 
-		tmp += GET_INSN_LENGTH(*(u16 *)tmp);
+		tmp += read_insn_length((u16 *)tmp);
 	}
 
 	return false;
@@ -75,9 +75,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 		return -EILSEQ;
 
 	/* copy instruction */
-	p->opcode = (kprobe_opcode_t)(*insn++);
-	if (GET_INSN_LENGTH(p->opcode) == 4)
-		p->opcode |= (kprobe_opcode_t)(*insn) << 16;
+	*((u16 *)&p->opcode) = (*insn++);
+	if (read_insn_length(&p->opcode) == 4)
+		p->opcode = (kprobe_opcode_t)(*(u32 *)p->addr);
 
 	/* decode instruction */
 	switch (riscv_probe_decode_insn(p->addr, &p->ainsn.api)) {
@@ -107,16 +107,24 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 /* install breakpoint in text */
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	size_t len = GET_INSN_LENGTH(p->opcode);
-	u32 insn = len == 4 ? __BUG_INSN_32 : __BUG_INSN_16;
+	size_t len = read_insn_length(&p->opcode);
+	u32 insn;
+
+	if (len == 4)
+		insn = cpu_to_le32(__BUG_INSN_32);
+	else {
+		insn = cpu_to_le16(__BUG_INSN_16);
+		insn |= cpu_to_le16(__BUG_INSN_16) << 16;
+	}
 
+	pr_info("%s: patching %px (%d bytes)\n", __func__, p->addr, (int)len);
 	patch_text(p->addr, &insn, len);
 }
 
 /* remove breakpoint from text */
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-	size_t len = GET_INSN_LENGTH(p->opcode);
+	size_t len = read_insn_length(&p->opcode);
 
 	patch_text(p->addr, &p->opcode, len);
 }
@@ -336,7 +344,7 @@ kprobe_single_step_handler(struct pt_regs *regs)
 	struct kprobe *cur = kprobe_running();
 
 	if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) &&
-	    ((unsigned long)&cur->ainsn.api.insn[0] + GET_INSN_LENGTH(cur->opcode) == addr)) {
+	    ((unsigned long)&cur->ainsn.api.insn[0] + read_insn_length(&cur->opcode) == addr)) {
 		kprobes_restore_local_irqflag(kcb, regs);
 		post_kprobe_handler(cur, kcb, regs);
 		return true;
diff --git a/arch/riscv/kernel/probes/uprobes.c b/arch/riscv/kernel/probes/uprobes.c
index 4b3dc8beaf77..e31c1dd337d5 100644
--- a/arch/riscv/kernel/probes/uprobes.c
+++ b/arch/riscv/kernel/probes/uprobes.c
@@ -12,9 +12,9 @@
 bool is_swbp_insn(uprobe_opcode_t *insn)
 {
 #ifdef CONFIG_RISCV_ISA_C
-	return (*insn & 0xffff) == UPROBE_SWBP_INSN;
+	return (*(u16 *)insn) == cpu_to_le16(UPROBE_SWBP_INSN);
 #else
-	return *insn == UPROBE_SWBP_INSN;
+	return *insn == cpu_to_le32(UPROBE_SWBP_INSN);
 #endif
 }
 
@@ -35,7 +35,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
 
 	opcode = *(probe_opcode_t *)(&auprobe->insn[0]);
 
-	auprobe->insn_size = GET_INSN_LENGTH(opcode);
+	auprobe->insn_size = GET_INSN_LENGTH(le32_to_cpu(opcode));
 
 	switch (riscv_probe_decode_insn(&opcode, &auprobe->api)) {
 	case INSN_REJECTED:
@@ -172,8 +172,8 @@ void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
 
 	/* Add ebreak behind opcode to simulate singlestep */
 	if (vaddr) {
-		dst += GET_INSN_LENGTH(*(probe_opcode_t *)src);
-		*(uprobe_opcode_t *)dst = __BUG_INSN_32;
+		dst += read_insn_length(src);
+		*(uprobe_opcode_t *)dst = cpu_to_le32(__BUG_INSN_32);
 	}
 
 	kunmap_atomic(kaddr);
-- 
2.37.2.352.g3c44437643


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  parent reply	other threads:[~2024-12-20 15:58 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-20 15:57 RFC: riscv64 big endian system attempt Ben Dooks
2024-12-20 15:57 ` [RFC 01/15] riscv: add initial kconfig and build flags for big-endian Ben Dooks
2024-12-20 15:57 ` [RFC 02/15] add __RISCVEB__ to byteorder.h Ben Dooks
2024-12-20 15:57 ` [RFC 03/15] riscv: disable vector if big-endian, gcc unsupported option Ben Dooks
2024-12-20 15:57 ` [RFC 04/15] riscv: word-at-atime: move to generic if we're big endian Ben Dooks
2024-12-20 15:57 ` [RFC 05/15] riscv: asm: use .insn for making custom instructioons Ben Dooks
2024-12-20 15:57 ` [RFC 06/15] intiial header work Ben Dooks
2024-12-20 15:57 ` [RFC 07/15] kconfig: remove CONFIG_COMAPT for big-endian (compat cods doesn't build atm) Ben Dooks
2024-12-20 15:57 ` [RFC 08/15] defconfig: add our build config Ben Dooks
2024-12-20 15:57 ` [RFC 09/15] temp: remove various library optimisations Ben Dooks
2024-12-20 15:57 ` [RFC 10/15] riscv: fixup use of natural endian on instructions Ben Dooks
2024-12-20 15:57 ` [RFC 11/15] add todo on fpu Ben Dooks
2024-12-20 15:57 ` [RFC 12/15] riscv: bpf: big endian fixes, updated BPF_ALU ops Ben Dooks
2024-12-20 15:57 ` Ben Dooks [this message]
2024-12-20 15:58 ` [RFC 14/15] riscv: ftrace big endian updates Ben Dooks
2024-12-20 15:58 ` [RFC 15/15] riscv: traps: make insn fetch common in unknown instruction Ben Dooks
2024-12-20 19:53 ` RFC: riscv64 big endian system attempt Olof Johansson
2025-01-09 17:46   ` Palmer Dabbelt

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=20241220155801.1988785-14-ben.dooks@codethink.co.uk \
    --to=ben.dooks@codethink.co.uk \
    --cc=felix.chong@codethink.co.uk \
    --cc=lawrence.hunter@codethink.co.uk \
    --cc=linux-riscv@lists.infradead.org \
    --cc=roan.richmond@codethink.co.uk \
    /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