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 10/15] riscv: fixup use of natural endian on instructions
Date: Fri, 20 Dec 2024 15:57:56 +0000	[thread overview]
Message-ID: <20241220155801.1988785-11-ben.dooks@codethink.co.uk> (raw)
In-Reply-To: <20241220155801.1988785-1-ben.dooks@codethink.co.uk>

The priveldged ISA spec says that all instructions should
be treated as little endian, so if we load them from memory
we should do le{16,32}_to_cpu on these and the reverse when
storing.

This fixes jump_label, bug and related functions for big endian
builds.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
---
 arch/riscv/kernel/alternative.c      | 10 +++++++++-
 arch/riscv/kernel/cfi.c              |  3 ++-
 arch/riscv/kernel/jump_label.c       |  3 ++-
 arch/riscv/kernel/traps.c            |  2 ++
 arch/riscv/kernel/traps_misaligned.c |  3 +++
 5 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index 0128b161bfda..a2c8f0a5bca9 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -62,11 +62,16 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
 	}
 }
 
+static u32 get_u16(u16 *ptr)
+{
+	return le16_to_cpu(*ptr);
+}
+
 static u32 riscv_instruction_at(void *p)
 {
 	u16 *parcel = p;
 
-	return (u32)parcel[0] | (u32)parcel[1] << 16;
+	return (u32)get_u16(parcel+0) | (u32)get_u16(parcel+1) << 16;
 }
 
 static void riscv_alternative_fix_auipc_jalr(void *ptr, u32 auipc_insn,
@@ -83,6 +88,8 @@ static void riscv_alternative_fix_auipc_jalr(void *ptr, u32 auipc_insn,
 	riscv_insn_insert_utype_itype_imm(&call[0], &call[1], imm);
 
 	/* patch the call place again */
+	call[0] = cpu_to_le32(call[0]);
+	call[1] = cpu_to_le32(call[1]);
 	patch_text_nosync(ptr, call, sizeof(u32) * 2);
 }
 
@@ -98,6 +105,7 @@ static void riscv_alternative_fix_jal(void *ptr, u32 jal_insn, int patch_offset)
 	riscv_insn_insert_jtype_imm(&jal_insn, imm);
 
 	/* patch the call place again */
+	jal_insn = cpu_to_le32(jal_insn);
 	patch_text_nosync(ptr, &jal_insn, sizeof(u32));
 }
 
diff --git a/arch/riscv/kernel/cfi.c b/arch/riscv/kernel/cfi.c
index 64bdd3e1ab8c..bd35ddbcbcee 100644
--- a/arch/riscv/kernel/cfi.c
+++ b/arch/riscv/kernel/cfi.c
@@ -37,15 +37,16 @@ static bool decode_cfi_insn(struct pt_regs *regs, unsigned long *target,
 	 */
 	if (get_kernel_nofault(insn, (void *)regs->epc - 4))
 		return false;
+	insn = le32_to_cpu(insn);
 	if (!riscv_insn_is_beq(insn))
 		return false;
-
 	*type = (u32)regs_ptr[RV_EXTRACT_RS1_REG(insn)];
 
 	if (get_kernel_nofault(insn, (void *)regs->epc) ||
 	    get_kernel_nofault(insn, (void *)regs->epc + GET_INSN_LENGTH(insn)))
 		return false;
 
+	insn = le32_to_cpu(insn);
 	if (riscv_insn_is_jalr(insn))
 		rs1_num = RV_EXTRACT_RS1_REG(insn);
 	else if (riscv_insn_is_c_jalr(insn))
diff --git a/arch/riscv/kernel/jump_label.c b/arch/riscv/kernel/jump_label.c
index 11ad789c60c6..e8a9301ec0bf 100644
--- a/arch/riscv/kernel/jump_label.c
+++ b/arch/riscv/kernel/jump_label.c
@@ -19,7 +19,7 @@ bool arch_jump_label_transform_queue(struct jump_entry *entry,
 				     enum jump_label_type type)
 {
 	void *addr = (void *)jump_entry_code(entry);
-	u32 insn;
+	__le32 insn;
 
 	if (type == JUMP_LABEL_JMP) {
 		long offset = jump_entry_target(entry) - jump_entry_code(entry);
@@ -36,6 +36,7 @@ bool arch_jump_label_transform_queue(struct jump_entry *entry,
 		insn = RISCV_INSN_NOP;
 	}
 
+	insn = cpu_to_le32(insn);
 	mutex_lock(&text_mutex);
 	patch_insn_write(addr, &insn, sizeof(insn));
 	mutex_unlock(&text_mutex);
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 51ebfd23e007..a475fd9310fd 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -253,6 +253,7 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
 	if (get_kernel_nofault(insn, (bug_insn_t *)pc))
 		return 0;
 
+	insn = le32_to_cpu(insn);
 	return GET_INSN_LENGTH(insn);
 }
 
@@ -399,6 +400,7 @@ int is_valid_bugaddr(unsigned long pc)
 		return 0;
 	if (get_kernel_nofault(insn, (bug_insn_t *)pc))
 		return 0;
+	insn = cpu_to_le32(insn);
 	if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32)
 		return (insn == __BUG_INSN_32);
 	else
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 1b9867136b61..21b2a4df185f 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -290,6 +290,7 @@ static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
 		 * below with the upper 16 bits half.
 		 */
 		insn &= GENMASK(15, 0);
+		insn = le16_to_cpu(insn);
 		if ((insn & __INSN_LENGTH_MASK) != __INSN_LENGTH_32) {
 			*r_insn = insn;
 			return 0;
@@ -297,12 +298,14 @@ static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
 		epc += sizeof(u16);
 		if (__read_insn(regs, tmp, epc, u16))
 			return -EFAULT;
+		tmp = le16_to_cpu(tmp);
 		*r_insn = (tmp << 16) | insn;
 
 		return 0;
 	} else {
 		if (__read_insn(regs, insn, epc, u32))
 			return -EFAULT;
+		insn = le32_to_cpu(insn);
 		if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) {
 			*r_insn = insn;
 			return 0;
-- 
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 ` Ben Dooks [this message]
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 ` [RFC 13/15] riscv: probes: sort out endian-ness Ben Dooks
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-11-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