On Mon, 19 Jan 2026 at 09:13, martin.kroening--- via qemu development
<[email protected]> wrote:
>
> Hi Philippe,
>
> On 18.01.26, 22:33, Philippe Mathieu-Daudé wrote:
>
> > > These functions are needed for CPUs that support runtime-configurable 
> > > endianness.
> > > In those cases, components such as semihosting need to perform
> > > runtime-dependent byte swaps.
> >
> > Are you targetting user or system emulation?
> >
> > I suppose user emulation, otherwise you'd have used the
> > "semihosting/uaccess.h" API.
> >
> > But then I'm confused because a user process can't change
> > the CPU endianness...

32-bit arm user-mode processes can change the CPU endianness,
incidentally; the SETEND instruction works at EL0.

> > Can you explain your use case?
>
> Thanks for asking! I am targeting system emulation. My use case is emulating
> bare-metal software such as an OS that switches the AArch64 CPU to big-endian
> mode during runtime.
>
> `{get,set}_user_u{64,32}` from "semihosting/uaccess.h" currently use
> `tswap{32,64}` from "exec/tswap.h", which do not respect runtime-configurable
> endianness.
>
> PATCH 1/2 introduces `cpu_tswap{32,64}`, which PATCH 2/2 integrates into
> "semihosting/uaccess.h". I can squash those commits if you prefer, of course.
> Or did I misunderstand your question?

So I think we do definitely want to have some setup where a
big-endian guest OS gets a big-endian semihosting ABI: the
semihosting spec is not very detailed on this but it does say

# Multi-byte values in memory must be formatted as pure little-endian
# or pure big-endian to match the endianness mapping configuration of
# the processor.

The question here is more (1) which specific endianness-config
bit do we want to be looking at and (2) what is the best API
and naming for the functions inside QEMU, to make them fit in
with some of the refactoring that Phil has been doing lately,
and to make them not liable to accidental misuse.

On (1) virtio_is_big_endian looks at the current data endianness
of the CPU, which is probably the most reasonable. (I don't know
what other semihosting implementations do -- the original "debug
ROM intercepts the SVC insn" implementation might well have been
hardcoded for "this is a big-endian ROM" vs "little-endian ROM".
But I don't think anybody could be relying on still getting
the little-endian ABI even when they temporarily use SETEND to
flip to big-endian.)

On (2):

> Alex was worried about expanding the use of `virtio_is_big_endian`:
>
> > Hmm looking at the description:
> >
> >     /**
> >      * @virtio_is_big_endian: Callback to return %true if a CPU which 
> > supports
> >      * runtime configurable endianness is currently big-endian.
> >      * Non-configurable CPUs can use the default implementation of this 
> > method.
> >      * This method should not be used by any callers other than the pre-1.0
> >      * virtio devices.
> >      */
> >     bool (*virtio_is_big_endian)(CPUState *cpu);
> >
> > I'm not sure if we want to expand the usage of this hack. I think
> > Philippe is hoping to get rid of these warts eventually. Of course we
> > could rename the method and just provide a way to get the current
> > systems endianess.
>
> While not being very familiar with QEMU's source code, something like this
> seems necessary to me. I can rename `virtio_is_big_endian` to `is_big_endian`
> and `cpu_virtio_is_big_endian` to `cpu_is_big_endian` if you prefer that.

The reason for naming these functions the way we have now is
that we really didn't want them to be a "this looks like the
right function to use for my purpose" general name like
"is_big_endian". Almost nothing in QEMU outside the CPU itself
should need to know about the data endianness of the CPU,
because in real hardware the devices can't tell what the CPU
is set up as, they just get/send data. The exceptions are
legacy virtio (which is a mistake that was made because nobody
was thinking about it in the original virtio device design)
and some oddball interfaces like semihosting. So the name is
intended to push people away from using it (and towards e.g.
target_big_endian()).

thanks
-- PMM

Reply via email to