aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Bergren <bdragon@FreeBSD.org>2020-09-23 00:09:29 +0000
committerBrandon Bergren <bdragon@FreeBSD.org>2020-09-23 00:09:29 +0000
commit4efb1ca7d2a44cfb33d7f9e18bd92f8d68dcfee0 (patch)
treef8ffa565ee6c1dad7596d4454e221c6877aa5c36
parent15be37cb7fb16627870878f7a69aa8467430f32a (diff)
downloadsrc-4efb1ca7d2a44cfb33d7f9e18bd92f8d68dcfee0.tar.gz
src-4efb1ca7d2a44cfb33d7f9e18bd92f8d68dcfee0.zip
[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.
Notes
Notes: svn path=/head/; revision=366037
-rw-r--r--sys/conf/options.powerpc1
-rw-r--r--sys/powerpc/conf/GENERIC641
-rw-r--r--sys/powerpc/conf/NOTES1
-rw-r--r--sys/powerpc/ofw/ofwcall64.S10
-rw-r--r--sys/powerpc/powernv/opalcall.S11
5 files changed, 24 insertions, 0 deletions
diff --git a/sys/conf/options.powerpc b/sys/conf/options.powerpc
index 6e9eb81ecaf0..1a22f931450a 100644
--- a/sys/conf/options.powerpc
+++ b/sys/conf/options.powerpc
@@ -29,6 +29,7 @@ MAMBO
POWERNV opt_platform.h
PSERIES
PSIM
+QEMU opt_platform.h
SC_OFWFB opt_ofwfb.h
diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64
index a70cd0db605d..18eedb7f927a 100644
--- a/sys/powerpc/conf/GENERIC64
+++ b/sys/powerpc/conf/GENERIC64
@@ -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
diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES
index 74a03f2cedcd..c41a0a61184d 100644
--- a/sys/powerpc/conf/NOTES
+++ b/sys/powerpc/conf/NOTES
@@ -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
diff --git a/sys/powerpc/ofw/ofwcall64.S b/sys/powerpc/ofw/ofwcall64.S
index 481c109affd2..3230cdf79c37 100644
--- a/sys/powerpc/ofw/ofwcall64.S
+++ b/sys/powerpc/ofw/ofwcall64.S
@@ -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
diff --git a/sys/powerpc/powernv/opalcall.S b/sys/powerpc/powernv/opalcall.S
index 1d1f60353ade..56ba5c7f1863 100644
--- a/sys/powerpc/powernv/opalcall.S
+++ b/sys/powerpc/powernv/opalcall.S
@@ -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