We turn the virtio_is_big_endian() helper into a target dependant hook to compute endianness for legacy virtio devices.
We base it on the OS endian, as reflected by the endianness of the interrupt vectors (handled through the ILE bit in the LPCR register). Using first_cpu to fetch the registers from KVM may look arbitrary and awkward, but it is okay because KVM sets/unsets the ILE bit on all CPUs. Note that Book3e has no LPCR and worse, has a unrelated spr at the same index... I did not find better than strcmp() to ensure we are using the correct register. Suggested-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> [ re-use the existing virito_is_big_endian() helper, check we have LPCR, Greg Kurz <gk...@linux.vnet.ibm.com> ] Signed-off-by: Greg Kurz <gk...@linux.vnet.ibm.com> Reviewed-by: Alexander Graf <ag...@suse.de> --- Changes since v5: - merged with the existing virtio_is_big_endian() helper - ensure cpu has LPCR exec.c | 2 +- target-ppc/misc_helper.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index e6777d0..cf98d42 100644 --- a/exec.c +++ b/exec.c @@ -2740,7 +2740,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, } #endif -#if !defined(CONFIG_USER_ONLY) +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_PPC) /* * A helper function for the _utterly broken_ virtio device model to find out if diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c index 2eb2fa6..971cafe 100644 --- a/target-ppc/misc_helper.c +++ b/target-ppc/misc_helper.c @@ -20,6 +20,8 @@ #include "helper.h" #include "helper_regs.h" +#include "hw/virtio/virtio.h" +#include "sysemu/kvm.h" /*****************************************************************************/ /* SPR accesses */ @@ -120,3 +122,19 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value) { hreg_store_msr(env, value, 0); } + +#if !defined(CONFIG_USER_ONLY) +bool virtio_is_big_endian(void) +{ + PowerPCCPU *cp = POWERPC_CPU(first_cpu); + CPUPPCState *env = &cp->env; + + /* NOTE: booke uses the same number for another unrelated spr. + */ + if (strcmp(env->spr_cb[SPR_LPCR].name, "LPCR")) { + return TARGET_WORDS_BIGENDIAN; + } else { + return !(env->spr[SPR_LPCR] & LPCR_ILE); + } +} +#endif