When running openbios-ppc32 on a ppc64 VM, we need to unset SF on every interrupt to ensure that things still work.
So far we've been using mtmsr for this operation, but according to the spec mtmsr doesn't set any bit above 32bit, so we were merely exploiting a bug in qemu before.
This patch adds a runtime check on PVR to see if we're running on a 64-bit capable CPU. If so, we use mtmsrd, which can set the high 32bits of MSR.
CC: Andreas Färber andreas.faerber@web.de Signed-off-by: Alexander Graf agraf@suse.de --- arch/ppc/qemu/start.S | 50 +++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/arch/ppc/qemu/start.S b/arch/ppc/qemu/start.S index 0d64568..70a4f92 100644 --- a/arch/ppc/qemu/start.S +++ b/arch/ppc/qemu/start.S @@ -37,9 +37,21 @@
#define EXCEPTION_PREAMBLE_TEMPLATE \ mtsprg1 r1 ; /* scratch */ \ + mfcr r1 ; \ + mtsprg2 r1 ; /* scratch */ \ + mtsprg3 r2 ; /* scratch */ \ + mfpvr r1 ; \ + lis r2, 0x330000@h ; /* lowest 64-bit PVR */ \ + cmplw r1, r2 ; \ + blt 1f; \ + oris r2, r2, 0x70000000@h ; /* highest 64-bit PVR */ \ + cmplw r1, r2 ; \ + bge 1f; \ + \ mfmsr r1 ; /* unset MSR_SF */ \ clrlwi r1,r1,0 ; \ - mtmsr r1 ; \ + mtmsrd r1 ; \ +1: \ mfsprg0 r1 ; /* exception stack in sprg0 */ \ .ifc ULONG_SIZE, 8 ; \ addi r1,r1,-(40 * ULONG_SIZE) ; /* push exception frame */ \ @@ -50,6 +62,7 @@ stl r0,(0 * ULONG_SIZE)(r1) ; /* save r0 */ \ mfsprg1 r0 ; \ stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \ + mfsprg3 r2 ; \ stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \ stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \ stl r4,(4 * ULONG_SIZE)(r1) ; \ @@ -85,7 +98,7 @@ \ mflr r0 ; \ stl r0,(13 * ULONG_SIZE)(r1) ; \ - mfcr r0 ; \ + mfsprg2 r0 ; \ stl r0,(14 * ULONG_SIZE)(r1) ; \ mfctr r0 ; \ stl r0,(15 * ULONG_SIZE)(r1) ; \ @@ -301,14 +314,12 @@ VECTOR( 0x100, "SRE" ): ILLEGAL_VECTOR( 0x200 )
VECTOR( 0x300, "DSI" ): - EXCEPTION_PREAMBLE - b call_dsi_exception + b real_dsi
ILLEGAL_VECTOR( 0x380 )
VECTOR( 0x400, "ISI" ): - EXCEPTION_PREAMBLE - b call_isi_exception + b real_isi
ILLEGAL_VECTOR( 0x480 )
@@ -359,6 +370,14 @@ VECTOR( 0x2200, "ISI_64" ):
#endif
+real_dsi: + EXCEPTION_PREAMBLE + b call_dsi_exception + +real_isi: + EXCEPTION_PREAMBLE + b call_isi_exception + GLOBL(__vectors_end):
/************************************************************************/ @@ -368,10 +387,25 @@ GLOBL(__vectors_end): GLOBL(_entry):
#ifdef CONFIG_PPC_64BITSUPPORT - /* clear MSR, disable MMU */ - li r0,0 + + mfpvr r3 + lis r4, 0x330000@h /* lowest 64-bit PVR */ + cmplw r3, r4 + blt no_64bit + oris r4, r4, 0x70000000@h /* highest 64-bit PVR */ + cmplw r3, r4 + bge no_64bit + + /* clear MSR, disable MMU, SF */ + mtmsrd r0 + b real_entry + +no_64bit: + /* clear MSR, disable MMU */ mtmsr r0 + +real_entry: #endif
/* copy exception vectors */