From: Michael Neuling <mikey@neuling.org>
Subject: powerpc: Fix context switch DSCR on POWER8
Git-commit: 2517617e0de65f8f7cfe75cae745d06b1fa98586
Patch-mainline: v3.11-rc5
References: bsc#912129, FATE#317619

 powerpc: Fix context switch DSCR on POWER8

POWER8 allows the DSCR to be accessed directly from userspace via a new SPR
number 0x3 (Rather than 0x11.  DSCR SPR number 0x11 is still used on POWER8 but
like POWER7, is only accessible in HV and OS modes).  Currently, we allow this
by setting H/FSCR DSCR bit on boot.

Unfortunately this doesn't work, as the kernel needs to see the DSCR change so
that it knows to no longer restore the system wide version of DSCR on context
switch (ie. to set thread.dscr_inherit).

This clears the H/FSCR DSCR bit initially.  If a process then accesses the DSCR
(via SPR 0x3), it'll trap into the kernel where we set thread.dscr_inherit in
facility_unavailable_exception().

We also change _switch() so that we set or clear the H/FSCR DSCR bit based on
the thread.dscr_inherit.

Signed-off-by: Michael Neuling <mikey@neuling.org>
Cc: <stable@vger.kernel.org> [v3.10]
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Backported-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Acked-by: Torsten Duwe <duwe@suse.de>
---
 arch/powerpc/kernel/entry_64.S | 17 ++++++++++++++++-
 arch/powerpc/kernel/traps.c    | 11 +++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -576,9 +576,24 @@ BEGIN_FTR_SECTION
 	ld	r7,DSCR_DEFAULT@toc(2)
 	ld	r0,THREAD_DSCR(r4)
 	cmpwi	r6,0
+	li	r8, FSCR_DSCR
 	bne	1f
 	ld	r0,0(r7)
-1:	cmpd	r0,r25
+	b       3f
+1:
+BEGIN_FTR_SECTION_NESTED(70)
+	mfspr   r6, SPRN_FSCR
+	or      r6, r6, r8
+	mtspr   SPRN_FSCR, r6
+	b       4f
+END_FTR_SECTION_NESTED(CPU_FTR_ARCH_207S, CPU_FTR_ARCH_207S, 70)
+3:
+BEGIN_FTR_SECTION_NESTED(70)
+	mfspr   r6, SPRN_FSCR
+	andc    r6, r6, r8
+	mtspr   SPRN_FSCR, r6
+END_FTR_SECTION_NESTED(CPU_FTR_ARCH_207S, CPU_FTR_ARCH_207S, 70)
+4:	cmpd    r0,r25
 	beq	2f
 	mtspr	SPRN_DSCR,r0
 2:
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1144,6 +1144,17 @@ void facility_unavailable_exception(stru
 
 	value = mfspr(SPRN_FSCR);
 	status = value >> 56;
+
+	if (status == FSCR_DSCR_LG) {
+		/* User is acessing the DSCR.  Set the inherit bit and allow
+		 * the user to set it directly in future by setting via the
+		 * FSCR DSCR bit.
+		 */
+		current->thread.dscr_inherit = 1;
+		mtspr(SPRN_FSCR,  value | FSCR_DSCR);
+		return;
+	}
+
 	if ((status < ARRAY_SIZE(facility_strings)) &&
 				facility_strings[status])
 		facility = facility_strings[status];
