* Re: [PATCH 1/1] linux-user: add support for big endian variants of riscv
2023-06-30 11:14 ` [PATCH 1/1] " Rory Bolt
@ 2023-06-29 21:43 ` Palmer Dabbelt
2023-07-24 3:22 ` Alistair Francis
0 siblings, 1 reply; 4+ messages in thread
From: Palmer Dabbelt @ 2023-06-29 21:43 UTC (permalink / raw)
To: rory.opensource; +Cc: qemu-riscv, qemu-devel, rory.opensource
On Fri, 30 Jun 2023 04:14:09 PDT (-0700), rory.opensource@gmail.com wrote:
> RISCV architecture supports an optional big endian mode of operation.
> In this mode, data accesses are treated as big endian, while code is
> always in little endian format. This is similar to how the ARM
> architecture treats it's optional bi-endian support. This patch adds
> support for big endian RISCV operation to linux-user.
We don't have BE support in Linux yet. IIRC we've had some other
linux-user stuff go in with a "we'll change it to match whatever uABI
Linux ends up with" sort of caveat, but I might be mistaken. I'm not
opposed to doing that sort of thing for BE as well. I don't remember
what the right way to indicate that is, though.
> Signed-off-by: rory.opensource@gmail.com
> ---
> configs/targets/riscv64be-linux-user.mak | 7 +++++++
> configure | 1 +
> linux-user/elfload.c | 10 ++++++++++
> linux-user/include/host/riscv/host-signal.h | 3 +++
> linux-user/riscv/signal.c | 5 +++++
> linux-user/riscv/target_syscall.h | 8 ++++++++
> scripts/probe-gdb-support.py | 4 ++--
> scripts/qemu-binfmt-conf.sh | 12 ++++++++++--
> target/riscv/cpu.c | 5 +++++
> target/riscv/translate.c | 13 +++++++++++++
> 10 files changed, 64 insertions(+), 4 deletions(-)
> create mode 100644 configs/targets/riscv64be-linux-user.mak
>
> diff --git a/configs/targets/riscv64be-linux-user.mak b/configs/targets/riscv64be-linux-user.mak
> new file mode 100644
> index 0000000000..f22f5f0971
> --- /dev/null
> +++ b/configs/targets/riscv64be-linux-user.mak
> @@ -0,0 +1,7 @@
> +TARGET_ARCH=riscv64
> +TARGET_BASE_ARCH=riscv
> +TARGET_ABI_DIR=riscv
> +TARGET_BIG_ENDIAN=y
> +TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
> +CONFIG_SEMIHOSTING=y
> +CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
> diff --git a/configure b/configure
> index 2b41c49c0d..90795a0e9f 100755
> --- a/configure
> +++ b/configure
> @@ -1190,6 +1190,7 @@ fi
> : ${cross_prefix_ppc64="powerpc64-linux-gnu-"}
> : ${cross_prefix_ppc64le="$cross_prefix_ppc64"}
> : ${cross_prefix_riscv64="riscv64-linux-gnu-"}
> +: ${cross_prefix_riscv64be="riscv64be-linux-gnu-"}
> : ${cross_prefix_s390x="s390x-linux-gnu-"}
> : ${cross_prefix_sh4="sh4-linux-gnu-"}
> : ${cross_prefix_sparc64="sparc64-linux-gnu-"}
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 9a2ec568b0..e0204c7069 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1681,8 +1681,18 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
>
> #ifdef TARGET_RISCV32
> #define ELF_CLASS ELFCLASS32
> +#if TARGET_BIG_ENDIAN
> +#define ELF_PLATFORM "riscv32be"
> +#else
> +#define ELF_PLATFORM "riscv32"
> +#endif
> #else
> #define ELF_CLASS ELFCLASS64
> +#if TARGET_BIG_ENDIAN
> +#define ELF_PLATFORM "riscv64be"
> +#else
> +#define ELF_PLATFORM "riscv64"
> +#endif
> #endif
>
> #define ELF_HWCAP get_elf_hwcap()
> diff --git a/linux-user/include/host/riscv/host-signal.h b/linux-user/include/host/riscv/host-signal.h
> index decacb2325..b3f2735261 100644
> --- a/linux-user/include/host/riscv/host-signal.h
> +++ b/linux-user/include/host/riscv/host-signal.h
> @@ -38,6 +38,9 @@ static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
> */
> const uint16_t *pinsn = (const uint16_t *)host_signal_pc(uc);
> uint16_t insn = pinsn[0];
> +#if TARGET_BIG_ENDIAN
> + insn = (insn << 8) | (insn >> 8);
> +#endif
>
> /* 16-bit instructions */
> switch (insn & 0xe003) {
> diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
> index eaa168199a..1d9e3413fb 100644
> --- a/linux-user/riscv/signal.c
> +++ b/linux-user/riscv/signal.c
> @@ -199,8 +199,13 @@ void setup_sigtramp(abi_ulong sigtramp_page)
> uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
> assert(tramp != NULL);
>
> +#if TARGET_BIG_ENDIAN
> + __put_user(0x9308b008, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
> + __put_user(0x73000000, tramp + 1); /* ecall */
> +#else
> __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
> __put_user(0x00000073, tramp + 1); /* ecall */
> +#endif
>
> default_rt_sigreturn = sigtramp_page;
> unlock_user(tramp, sigtramp_page, 8);
> diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h
> index 7601f10c28..88c0ac1351 100644
> --- a/linux-user/riscv/target_syscall.h
> +++ b/linux-user/riscv/target_syscall.h
> @@ -44,10 +44,18 @@ struct target_pt_regs {
> };
>
> #ifdef TARGET_RISCV32
> +#if TARGET_BIG_ENDIAN
> +#define UNAME_MACHINE "riscv32be"
> +#else
> #define UNAME_MACHINE "riscv32"
> +#endif
> #define UNAME_MINIMUM_RELEASE "5.4.0"
> #else
> +#if TARGET_BIG_ENDIAN
> +#define UNAME_MACHINE "riscv64be"
> +#else
> #define UNAME_MACHINE "riscv64"
> +#endif
> #define UNAME_MINIMUM_RELEASE "4.15.0"
> #endif
>
> diff --git a/scripts/probe-gdb-support.py b/scripts/probe-gdb-support.py
> index 5755255966..a1e0905a10 100644
> --- a/scripts/probe-gdb-support.py
> +++ b/scripts/probe-gdb-support.py
> @@ -41,8 +41,8 @@
> "or1k" : "or1k",
> "powerpc:common" : "ppc",
> "powerpc:common64" : ["ppc64", "ppc64le"],
> - "riscv:rv32" : "riscv32",
> - "riscv:rv64" : "riscv64",
> + "riscv:rv32" : ["riscv32", "riscv32be"],
> + "riscv:rv64" : ["riscv64", "riscv64be"],
> "s390:64-bit" : "s390x",
> "sh4" : ["sh4", "sh4eb"],
> "sparc": "sparc",
> diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
> index 6ef9f118d9..e1ee9f831b 100755
> --- a/scripts/qemu-binfmt-conf.sh
> +++ b/scripts/qemu-binfmt-conf.sh
> @@ -3,8 +3,8 @@
>
> qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
> ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
> -sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
> -microblaze microblazeel or1k x86_64 hexagon loongarch64"
> +sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv32be riscv64 riscv64be \
> +xtensa xtensaeb microblaze microblazeel or1k x86_64 hexagon loongarch64"
>
> i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
> i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> @@ -112,10 +112,18 @@ riscv32_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
> riscv32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> riscv32_family=riscv
>
> +riscv32be_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3'
> +riscv32be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
> +riscv32be_family=riscv
> +
> riscv64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00'
> riscv64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> riscv64_family=riscv
>
> +riscv64be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3'
> +riscv64be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
> +riscv64be_family=riscv
> +
> xtensa_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e\x00'
> xtensa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> xtensa_family=xtensa
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 881bddf393..26fb3e830d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -873,6 +873,11 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
> default:
> g_assert_not_reached();
> }
> +#if TARGET_BIG_ENDIAN
> + info->endian = BFD_ENDIAN_LITTLE;
> +#else
> + info->endian = BFD_ENDIAN_BIG;
> +#endif
> }
>
> static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 8a33da811e..3991ff6be0 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -1157,9 +1157,16 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
> }
> } else {
> uint32_t opcode32 = opcode;
> +#if TARGET_BIG_ENDIAN
> + opcode32 = bswap16(opcode);
> +#endif
> opcode32 = deposit32(opcode32, 16, 16,
> translator_lduw(env, &ctx->base,
> ctx->base.pc_next + 2));
> +#if TARGET_BIG_ENDIAN
> + opcode32 = (opcode32) << 16 | (opcode32 >> 16);
> + opcode32 = bswap32(opcode32);
> +#endif
> ctx->opcode = opcode32;
>
> for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
> @@ -1230,6 +1237,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
> DisasContext *ctx = container_of(dcbase, DisasContext, base);
> CPURISCVState *env = cpu->env_ptr;
> uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
> +#if TARGET_BIG_ENDIAN
> + opcode16 = bswap16(opcode16);
> +#endif
>
> ctx->ol = ctx->xl;
> decode_opc(env, ctx, opcode16);
> @@ -1244,6 +1254,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
>
> if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
> uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
> +#if TARGET_BIG_ENDIAN
> + next_insn = bswap16(next_insn);
> +#endif
> int len = insn_len(next_insn);
>
> if (!is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
Nothing's jumping out as wrong to me, but I haven't given BE much
thought so I wouldn't be surprised if there's something wrong somewhere.
I'm happy to look a bit deeper, but let's see if the unstable uABI stuff
is OK with folks first?
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 0/1] linux-user: add support for big endian variants of riscv
@ 2023-06-30 11:14 Rory Bolt
2023-06-30 11:14 ` [PATCH 1/1] " Rory Bolt
0 siblings, 1 reply; 4+ messages in thread
From: Rory Bolt @ 2023-06-30 11:14 UTC (permalink / raw)
To: qemu-riscv; +Cc: qemu-devel, Rory Bolt
Rory Bolt (1):
linux-user: add support for big endian variants of riscv
configs/targets/riscv64be-linux-user.mak | 7 +++++++
configure | 1 +
linux-user/elfload.c | 10 ++++++++++
linux-user/include/host/riscv/host-signal.h | 3 +++
linux-user/riscv/signal.c | 5 +++++
linux-user/riscv/target_syscall.h | 8 ++++++++
scripts/probe-gdb-support.py | 4 ++--
scripts/qemu-binfmt-conf.sh | 12 ++++++++++--
target/riscv/cpu.c | 5 +++++
target/riscv/translate.c | 13 +++++++++++++
10 files changed, 64 insertions(+), 4 deletions(-)
create mode 100644 configs/targets/riscv64be-linux-user.mak
--
2.39.3
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/1] linux-user: add support for big endian variants of riscv
2023-06-30 11:14 [PATCH 0/1] linux-user: add support for big endian variants of riscv Rory Bolt
@ 2023-06-30 11:14 ` Rory Bolt
2023-06-29 21:43 ` Palmer Dabbelt
0 siblings, 1 reply; 4+ messages in thread
From: Rory Bolt @ 2023-06-30 11:14 UTC (permalink / raw)
To: qemu-riscv; +Cc: qemu-devel, Rory Bolt
RISCV architecture supports an optional big endian mode of operation.
In this mode, data accesses are treated as big endian, while code is
always in little endian format. This is similar to how the ARM
architecture treats it's optional bi-endian support. This patch adds
support for big endian RISCV operation to linux-user.
Signed-off-by: rory.opensource@gmail.com
---
configs/targets/riscv64be-linux-user.mak | 7 +++++++
configure | 1 +
linux-user/elfload.c | 10 ++++++++++
linux-user/include/host/riscv/host-signal.h | 3 +++
linux-user/riscv/signal.c | 5 +++++
linux-user/riscv/target_syscall.h | 8 ++++++++
scripts/probe-gdb-support.py | 4 ++--
scripts/qemu-binfmt-conf.sh | 12 ++++++++++--
target/riscv/cpu.c | 5 +++++
target/riscv/translate.c | 13 +++++++++++++
10 files changed, 64 insertions(+), 4 deletions(-)
create mode 100644 configs/targets/riscv64be-linux-user.mak
diff --git a/configs/targets/riscv64be-linux-user.mak b/configs/targets/riscv64be-linux-user.mak
new file mode 100644
index 0000000000..f22f5f0971
--- /dev/null
+++ b/configs/targets/riscv64be-linux-user.mak
@@ -0,0 +1,7 @@
+TARGET_ARCH=riscv64
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+TARGET_BIG_ENDIAN=y
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+CONFIG_SEMIHOSTING=y
+CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
diff --git a/configure b/configure
index 2b41c49c0d..90795a0e9f 100755
--- a/configure
+++ b/configure
@@ -1190,6 +1190,7 @@ fi
: ${cross_prefix_ppc64="powerpc64-linux-gnu-"}
: ${cross_prefix_ppc64le="$cross_prefix_ppc64"}
: ${cross_prefix_riscv64="riscv64-linux-gnu-"}
+: ${cross_prefix_riscv64be="riscv64be-linux-gnu-"}
: ${cross_prefix_s390x="s390x-linux-gnu-"}
: ${cross_prefix_sh4="sh4-linux-gnu-"}
: ${cross_prefix_sparc64="sparc64-linux-gnu-"}
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 9a2ec568b0..e0204c7069 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1681,8 +1681,18 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
#ifdef TARGET_RISCV32
#define ELF_CLASS ELFCLASS32
+#if TARGET_BIG_ENDIAN
+#define ELF_PLATFORM "riscv32be"
+#else
+#define ELF_PLATFORM "riscv32"
+#endif
#else
#define ELF_CLASS ELFCLASS64
+#if TARGET_BIG_ENDIAN
+#define ELF_PLATFORM "riscv64be"
+#else
+#define ELF_PLATFORM "riscv64"
+#endif
#endif
#define ELF_HWCAP get_elf_hwcap()
diff --git a/linux-user/include/host/riscv/host-signal.h b/linux-user/include/host/riscv/host-signal.h
index decacb2325..b3f2735261 100644
--- a/linux-user/include/host/riscv/host-signal.h
+++ b/linux-user/include/host/riscv/host-signal.h
@@ -38,6 +38,9 @@ static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
*/
const uint16_t *pinsn = (const uint16_t *)host_signal_pc(uc);
uint16_t insn = pinsn[0];
+#if TARGET_BIG_ENDIAN
+ insn = (insn << 8) | (insn >> 8);
+#endif
/* 16-bit instructions */
switch (insn & 0xe003) {
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index eaa168199a..1d9e3413fb 100644
--- a/linux-user/riscv/signal.c
+++ b/linux-user/riscv/signal.c
@@ -199,8 +199,13 @@ void setup_sigtramp(abi_ulong sigtramp_page)
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
assert(tramp != NULL);
+#if TARGET_BIG_ENDIAN
+ __put_user(0x9308b008, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
+ __put_user(0x73000000, tramp + 1); /* ecall */
+#else
__put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
__put_user(0x00000073, tramp + 1); /* ecall */
+#endif
default_rt_sigreturn = sigtramp_page;
unlock_user(tramp, sigtramp_page, 8);
diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h
index 7601f10c28..88c0ac1351 100644
--- a/linux-user/riscv/target_syscall.h
+++ b/linux-user/riscv/target_syscall.h
@@ -44,10 +44,18 @@ struct target_pt_regs {
};
#ifdef TARGET_RISCV32
+#if TARGET_BIG_ENDIAN
+#define UNAME_MACHINE "riscv32be"
+#else
#define UNAME_MACHINE "riscv32"
+#endif
#define UNAME_MINIMUM_RELEASE "5.4.0"
#else
+#if TARGET_BIG_ENDIAN
+#define UNAME_MACHINE "riscv64be"
+#else
#define UNAME_MACHINE "riscv64"
+#endif
#define UNAME_MINIMUM_RELEASE "4.15.0"
#endif
diff --git a/scripts/probe-gdb-support.py b/scripts/probe-gdb-support.py
index 5755255966..a1e0905a10 100644
--- a/scripts/probe-gdb-support.py
+++ b/scripts/probe-gdb-support.py
@@ -41,8 +41,8 @@
"or1k" : "or1k",
"powerpc:common" : "ppc",
"powerpc:common64" : ["ppc64", "ppc64le"],
- "riscv:rv32" : "riscv32",
- "riscv:rv64" : "riscv64",
+ "riscv:rv32" : ["riscv32", "riscv32be"],
+ "riscv:rv64" : ["riscv64", "riscv64be"],
"s390:64-bit" : "s390x",
"sh4" : ["sh4", "sh4eb"],
"sparc": "sparc",
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index 6ef9f118d9..e1ee9f831b 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -3,8 +3,8 @@
qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
-sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
-microblaze microblazeel or1k x86_64 hexagon loongarch64"
+sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv32be riscv64 riscv64be \
+xtensa xtensaeb microblaze microblazeel or1k x86_64 hexagon loongarch64"
i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
@@ -112,10 +112,18 @@ riscv32_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
riscv32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
riscv32_family=riscv
+riscv32be_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3'
+riscv32be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+riscv32be_family=riscv
+
riscv64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00'
riscv64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
riscv64_family=riscv
+riscv64be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3'
+riscv64be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+riscv64be_family=riscv
+
xtensa_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e\x00'
xtensa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
xtensa_family=xtensa
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 881bddf393..26fb3e830d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -873,6 +873,11 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
default:
g_assert_not_reached();
}
+#if TARGET_BIG_ENDIAN
+ info->endian = BFD_ENDIAN_LITTLE;
+#else
+ info->endian = BFD_ENDIAN_BIG;
+#endif
}
static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8a33da811e..3991ff6be0 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1157,9 +1157,16 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
}
} else {
uint32_t opcode32 = opcode;
+#if TARGET_BIG_ENDIAN
+ opcode32 = bswap16(opcode);
+#endif
opcode32 = deposit32(opcode32, 16, 16,
translator_lduw(env, &ctx->base,
ctx->base.pc_next + 2));
+#if TARGET_BIG_ENDIAN
+ opcode32 = (opcode32) << 16 | (opcode32 >> 16);
+ opcode32 = bswap32(opcode32);
+#endif
ctx->opcode = opcode32;
for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
@@ -1230,6 +1237,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
DisasContext *ctx = container_of(dcbase, DisasContext, base);
CPURISCVState *env = cpu->env_ptr;
uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
+#if TARGET_BIG_ENDIAN
+ opcode16 = bswap16(opcode16);
+#endif
ctx->ol = ctx->xl;
decode_opc(env, ctx, opcode16);
@@ -1244,6 +1254,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
+#if TARGET_BIG_ENDIAN
+ next_insn = bswap16(next_insn);
+#endif
int len = insn_len(next_insn);
if (!is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
--
2.39.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/1] linux-user: add support for big endian variants of riscv
2023-06-29 21:43 ` Palmer Dabbelt
@ 2023-07-24 3:22 ` Alistair Francis
0 siblings, 0 replies; 4+ messages in thread
From: Alistair Francis @ 2023-07-24 3:22 UTC (permalink / raw)
To: Palmer Dabbelt; +Cc: rory.opensource, qemu-riscv, qemu-devel
On Fri, Jun 30, 2023 at 7:45 AM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>
> On Fri, 30 Jun 2023 04:14:09 PDT (-0700), rory.opensource@gmail.com wrote:
> > RISCV architecture supports an optional big endian mode of operation.
> > In this mode, data accesses are treated as big endian, while code is
> > always in little endian format. This is similar to how the ARM
> > architecture treats it's optional bi-endian support. This patch adds
> > support for big endian RISCV operation to linux-user.
>
> We don't have BE support in Linux yet. IIRC we've had some other
> linux-user stuff go in with a "we'll change it to match whatever uABI
> Linux ends up with" sort of caveat, but I might be mistaken. I'm not
> opposed to doing that sort of thing for BE as well. I don't remember
> what the right way to indicate that is, though.
>
> > Signed-off-by: rory.opensource@gmail.com
> > ---
> > configs/targets/riscv64be-linux-user.mak | 7 +++++++
> > configure | 1 +
> > linux-user/elfload.c | 10 ++++++++++
> > linux-user/include/host/riscv/host-signal.h | 3 +++
> > linux-user/riscv/signal.c | 5 +++++
> > linux-user/riscv/target_syscall.h | 8 ++++++++
> > scripts/probe-gdb-support.py | 4 ++--
> > scripts/qemu-binfmt-conf.sh | 12 ++++++++++--
> > target/riscv/cpu.c | 5 +++++
> > target/riscv/translate.c | 13 +++++++++++++
> > 10 files changed, 64 insertions(+), 4 deletions(-)
> > create mode 100644 configs/targets/riscv64be-linux-user.mak
> >
> > diff --git a/configs/targets/riscv64be-linux-user.mak b/configs/targets/riscv64be-linux-user.mak
> > new file mode 100644
> > index 0000000000..f22f5f0971
> > --- /dev/null
> > +++ b/configs/targets/riscv64be-linux-user.mak
> > @@ -0,0 +1,7 @@
> > +TARGET_ARCH=riscv64
> > +TARGET_BASE_ARCH=riscv
> > +TARGET_ABI_DIR=riscv
> > +TARGET_BIG_ENDIAN=y
> > +TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
> > +CONFIG_SEMIHOSTING=y
> > +CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
> > diff --git a/configure b/configure
> > index 2b41c49c0d..90795a0e9f 100755
> > --- a/configure
> > +++ b/configure
> > @@ -1190,6 +1190,7 @@ fi
> > : ${cross_prefix_ppc64="powerpc64-linux-gnu-"}
> > : ${cross_prefix_ppc64le="$cross_prefix_ppc64"}
> > : ${cross_prefix_riscv64="riscv64-linux-gnu-"}
> > +: ${cross_prefix_riscv64be="riscv64be-linux-gnu-"}
> > : ${cross_prefix_s390x="s390x-linux-gnu-"}
> > : ${cross_prefix_sh4="sh4-linux-gnu-"}
> > : ${cross_prefix_sparc64="sparc64-linux-gnu-"}
> > diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> > index 9a2ec568b0..e0204c7069 100644
> > --- a/linux-user/elfload.c
> > +++ b/linux-user/elfload.c
> > @@ -1681,8 +1681,18 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
> >
> > #ifdef TARGET_RISCV32
> > #define ELF_CLASS ELFCLASS32
> > +#if TARGET_BIG_ENDIAN
> > +#define ELF_PLATFORM "riscv32be"
> > +#else
> > +#define ELF_PLATFORM "riscv32"
> > +#endif
> > #else
> > #define ELF_CLASS ELFCLASS64
> > +#if TARGET_BIG_ENDIAN
> > +#define ELF_PLATFORM "riscv64be"
> > +#else
> > +#define ELF_PLATFORM "riscv64"
> > +#endif
> > #endif
> >
> > #define ELF_HWCAP get_elf_hwcap()
> > diff --git a/linux-user/include/host/riscv/host-signal.h b/linux-user/include/host/riscv/host-signal.h
> > index decacb2325..b3f2735261 100644
> > --- a/linux-user/include/host/riscv/host-signal.h
> > +++ b/linux-user/include/host/riscv/host-signal.h
> > @@ -38,6 +38,9 @@ static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
> > */
> > const uint16_t *pinsn = (const uint16_t *)host_signal_pc(uc);
> > uint16_t insn = pinsn[0];
> > +#if TARGET_BIG_ENDIAN
> > + insn = (insn << 8) | (insn >> 8);
> > +#endif
> >
> > /* 16-bit instructions */
> > switch (insn & 0xe003) {
> > diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
> > index eaa168199a..1d9e3413fb 100644
> > --- a/linux-user/riscv/signal.c
> > +++ b/linux-user/riscv/signal.c
> > @@ -199,8 +199,13 @@ void setup_sigtramp(abi_ulong sigtramp_page)
> > uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
> > assert(tramp != NULL);
> >
> > +#if TARGET_BIG_ENDIAN
> > + __put_user(0x9308b008, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
> > + __put_user(0x73000000, tramp + 1); /* ecall */
> > +#else
> > __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
> > __put_user(0x00000073, tramp + 1); /* ecall */
> > +#endif
> >
> > default_rt_sigreturn = sigtramp_page;
> > unlock_user(tramp, sigtramp_page, 8);
> > diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h
> > index 7601f10c28..88c0ac1351 100644
> > --- a/linux-user/riscv/target_syscall.h
> > +++ b/linux-user/riscv/target_syscall.h
> > @@ -44,10 +44,18 @@ struct target_pt_regs {
> > };
> >
> > #ifdef TARGET_RISCV32
> > +#if TARGET_BIG_ENDIAN
> > +#define UNAME_MACHINE "riscv32be"
> > +#else
> > #define UNAME_MACHINE "riscv32"
> > +#endif
> > #define UNAME_MINIMUM_RELEASE "5.4.0"
> > #else
> > +#if TARGET_BIG_ENDIAN
> > +#define UNAME_MACHINE "riscv64be"
> > +#else
> > #define UNAME_MACHINE "riscv64"
> > +#endif
> > #define UNAME_MINIMUM_RELEASE "4.15.0"
> > #endif
> >
> > diff --git a/scripts/probe-gdb-support.py b/scripts/probe-gdb-support.py
> > index 5755255966..a1e0905a10 100644
> > --- a/scripts/probe-gdb-support.py
> > +++ b/scripts/probe-gdb-support.py
> > @@ -41,8 +41,8 @@
> > "or1k" : "or1k",
> > "powerpc:common" : "ppc",
> > "powerpc:common64" : ["ppc64", "ppc64le"],
> > - "riscv:rv32" : "riscv32",
> > - "riscv:rv64" : "riscv64",
> > + "riscv:rv32" : ["riscv32", "riscv32be"],
> > + "riscv:rv64" : ["riscv64", "riscv64be"],
> > "s390:64-bit" : "s390x",
> > "sh4" : ["sh4", "sh4eb"],
> > "sparc": "sparc",
> > diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
> > index 6ef9f118d9..e1ee9f831b 100755
> > --- a/scripts/qemu-binfmt-conf.sh
> > +++ b/scripts/qemu-binfmt-conf.sh
> > @@ -3,8 +3,8 @@
> >
> > qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
> > ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
> > -sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
> > -microblaze microblazeel or1k x86_64 hexagon loongarch64"
> > +sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv32be riscv64 riscv64be \
> > +xtensa xtensaeb microblaze microblazeel or1k x86_64 hexagon loongarch64"
> >
> > i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
> > i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> > @@ -112,10 +112,18 @@ riscv32_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
> > riscv32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> > riscv32_family=riscv
> >
> > +riscv32be_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3'
> > +riscv32be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
> > +riscv32be_family=riscv
> > +
> > riscv64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00'
> > riscv64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> > riscv64_family=riscv
> >
> > +riscv64be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3'
> > +riscv64be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
> > +riscv64be_family=riscv
> > +
> > xtensa_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e\x00'
> > xtensa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> > xtensa_family=xtensa
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 881bddf393..26fb3e830d 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -873,6 +873,11 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
> > default:
> > g_assert_not_reached();
> > }
> > +#if TARGET_BIG_ENDIAN
> > + info->endian = BFD_ENDIAN_LITTLE;
> > +#else
> > + info->endian = BFD_ENDIAN_BIG;
> > +#endif
> > }
> >
> > static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
> > diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> > index 8a33da811e..3991ff6be0 100644
> > --- a/target/riscv/translate.c
> > +++ b/target/riscv/translate.c
> > @@ -1157,9 +1157,16 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
> > }
> > } else {
> > uint32_t opcode32 = opcode;
> > +#if TARGET_BIG_ENDIAN
> > + opcode32 = bswap16(opcode);
> > +#endif
> > opcode32 = deposit32(opcode32, 16, 16,
> > translator_lduw(env, &ctx->base,
> > ctx->base.pc_next + 2));
> > +#if TARGET_BIG_ENDIAN
> > + opcode32 = (opcode32) << 16 | (opcode32 >> 16);
> > + opcode32 = bswap32(opcode32);
> > +#endif
> > ctx->opcode = opcode32;
> >
> > for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
> > @@ -1230,6 +1237,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
> > DisasContext *ctx = container_of(dcbase, DisasContext, base);
> > CPURISCVState *env = cpu->env_ptr;
> > uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
> > +#if TARGET_BIG_ENDIAN
> > + opcode16 = bswap16(opcode16);
> > +#endif
> >
> > ctx->ol = ctx->xl;
> > decode_opc(env, ctx, opcode16);
> > @@ -1244,6 +1254,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
> >
> > if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
> > uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
> > +#if TARGET_BIG_ENDIAN
> > + next_insn = bswap16(next_insn);
> > +#endif
> > int len = insn_len(next_insn);
> >
> > if (!is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
>
> Nothing's jumping out as wrong to me, but I haven't given BE much
> thought so I wouldn't be surprised if there's something wrong somewhere.
> I'm happy to look a bit deeper, but let's see if the unstable uABI stuff
> is OK with folks first?
If there isn't Linux support I'm reluctant to accept this as we have
no way to test it.
Alistair
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-07-24 3:23 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-30 11:14 [PATCH 0/1] linux-user: add support for big endian variants of riscv Rory Bolt
2023-06-30 11:14 ` [PATCH 1/1] " Rory Bolt
2023-06-29 21:43 ` Palmer Dabbelt
2023-07-24 3:22 ` Alistair Francis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).