[PowerPC64LE] Work around qemu TCG bug in mtmsrd emulation.

The TCG implementation of mtmsrd in qemu blindly copies the entire register
to the MSR, instead of the specific bit positions listed in the ISA.

This means that qemu will prematurely switch endian out from under the
running code instead of waiting for the rfid, causing an immediate trap
as it attempts to interpret the next instruction in the wrong endianness.

To work around this, ensure PSL_LE is still set before doing the mtmsrd.

In the future, we may wish to just turn off translation and unconditionally
use rfid to switch to the ofmsr instead of quasi-switching to the ofmsr.

Add a new platform option so this can be disabled. (And so that we can
conditonalize additional QEMU-specific hacks in the platform code.)

Sponsored by:	Tag1 Consulting, Inc.
This commit is contained in:
bdragon 2020-09-23 00:09:29 +00:00
parent af22ab81d8
commit d6fbb69b28
5 changed files with 24 additions and 0 deletions

View File

@ -29,6 +29,7 @@ MAMBO
POWERNV opt_platform.h
PSERIES
PSIM
QEMU opt_platform.h
SC_OFWFB opt_ofwfb.h

View File

@ -30,6 +30,7 @@ makeoptions WITH_CTF=1
options POWERMAC #NewWorld Apple PowerMacs
options PS3 #Sony Playstation 3
options MAMBO #IBM Mambo Full System Simulator
options QEMU #QEMU processor emulator
options PSERIES #PAPR-compliant systems (e.g. IBM p)
options POWERNV #Non-virtualized OpenPOWER systems

View File

@ -44,6 +44,7 @@ options POWERMAC #NewWorld Apple PowerMacs
#options PS3 #Sony Playstation 3
options PSIM #GDB PSIM ppc simulator
options MAMBO #IBM Mambo Full System Simulator
options QEMU #QEMU processor emulator
# The cpufreq(4) driver provides support for CPU frequency control
device cpufreq

View File

@ -32,6 +32,8 @@
#include <machine/spr.h>
#include <machine/asm.h>
#include "opt_platform.h"
#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
/*
@ -119,6 +121,10 @@ ASENTRY_NOPROF(ofwcall)
addis %r5,%r2,TOC_REF(ofmsr)@ha
ld %r5,TOC_REF(ofmsr)@l(%r5)
ld %r5,0(%r5)
#if defined(__LITTLE_ENDIAN__) && defined(QEMU)
/* QEMU hack: qemu does not emulate mtmsrd correctly! */
ori %r5,%r5,1 /* Leave PSR_LE set */
#endif
mtmsrd %r5
isync
@ -270,6 +276,10 @@ ASENTRY_NOPROF(rtascall)
addis %r7,%r2,TOC_REF(rtasmsr)@ha
ld %r7,TOC_REF(rtasmsr)@l(%r7)
ld %r7,0(%r7)
#ifdef __LITTLE_ENDIAN__
/* QEMU hack: qemu does not emulate mtmsrd correctly! */
ori %r7,%r7,1 /* Leave PSR_LE set */
#endif
mtmsrd %r7
isync

View File

@ -27,6 +27,8 @@
#include <machine/asm.h>
#include "opt_platform.h"
GLOBAL(opal_entrypoint)
.llong 0
GLOBAL(opal_data)
@ -70,8 +72,17 @@ ASENTRY(opal_call)
ld %r2,TOC_REF(opal_data)@l(%r2)
ld %r2,0(%r2)
#if defined(__LITTLE_ENDIAN__) && defined(QEMU)
/* QEMU hack: qemu does not emulate mtmsrd correctly! */
ori %r3,%r3,1 /* Leave PSR_LE set */
#endif
mtmsrd %r3
isync
#if defined(__LITTLE_ENDIAN__) && defined(QEMU)
/* Clean up from qemu hack */
xori %r3,%r3,1
#endif
/* Shift registers over */
mr %r3,%r4