From: Haren Myneni <haren@us.ibm.com>
Subject: powerpc: Implement PPR save/restore
Git-commit: 44e9309f1f357794b7ae93d5f3e3e6f11d2b8a7f
Patch-mainline: yes
References: bnc#795905,fate#314033 

When the task enters in to kernel space, the user defined priority (PPR)
will be saved in to PACA at the beginning of first level exception
vector and then copy from PACA to thread_info in second level vector.
PPR will be restored from thread_info before exits the kernel space.

P7 temporarily raises the thread priority to higher level during
exception until the program executes HMT_* calls. But it will not modify
PPR register. So we save PPR value whenever some register is available
to use and then calls HMT_MEDIUM to increase the priority. This feature
supports on P7 or later processors.

We save/ restore PPR for all exception vectors except system call entry.
GLIBC will be saving / restore for system calls. So the default PPR
value (3) will be set for the system call exit when the task returned
to the user space.

Signed-off-by: Haren Myneni <haren@us.ibm.com>
Acked-by: Torsten Duwe <duwe@suse.de>

diff -Naurp linux5/arch/powerpc/include/asm/exception-64s.h linux6/arch/powerpc/include/asm/exception-64s.h
--- linux5/arch/powerpc/include/asm/exception-64s.h	2012-12-22 01:13:02.000000000 -0800
+++ linux6/arch/powerpc/include/asm/exception-64s.h	2012-12-22 02:16:33.000000000 -0800
@@ -101,8 +101,9 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,C
 
 #define EXCEPTION_PROLOG_1(area)					\
 	GET_PACA(r13);							\
-	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
-	std	r10,area+EX_R10(r13);					\
+	std	r9,area+EX_R9(r13);	/* save r9 */			\
+	HMT_MEDIUM_PPR_SAVE(area, r9);					\
+	std	r10,area+EX_R10(r13);	/* save r10 - r12 */		\
 	std	r11,area+EX_R11(r13);					\
 	std	r12,area+EX_R12(r13);					\
 	BEGIN_FTR_SECTION_NESTED(66);					\
@@ -161,6 +162,7 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,C
 	std	r10,GPR1(r1);		/* save r1 in stackframe	*/ \
 	beq	4f;			/* if from kernel mode		*/ \
 	ACCOUNT_CPU_USER_ENTRY(r9, r10);				   \
+	SAVE_PPR(area, r9, r10);					   \
 4:	std	r2,GPR2(r1);		/* save r2 in stackframe	*/ \
 	SAVE_4GPRS(3, r1);		/* save r3 - r6 in stackframe	*/ \
 	SAVE_2GPRS(7, r1);		/* save r7, r8 in stackframe	*/ \
@@ -202,7 +204,7 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,C
 	. = loc;					\
 	.globl label##_pSeries;				\
 label##_pSeries:					\
-	HMT_MEDIUM;					\
+	HMT_MEDIUM_PPR_DISCARD;				\
 	DO_KVM	vec;					\
 	SET_SCRATCH0(r13);		/* save r13 */		\
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD)
@@ -211,18 +213,19 @@ label##_pSeries:					\
 	. = loc;					\
 	.globl label##_hv;				\
 label##_hv:						\
-	HMT_MEDIUM;					\
+	HMT_MEDIUM_PPR_DISCARD;				\
 	DO_KVM	vec;					\
 	SET_SCRATCH0(r13);	/* save r13 */		\
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV)
 
 #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h)			\
-	HMT_MEDIUM;							\
+	HMT_MEDIUM_PPR_DISCARD;						\
 	DO_KVM	vec;							\
 	SET_SCRATCH0(r13);    /* save r13 */				\
 	GET_PACA(r13);							\
-	std	r9,PACA_EXGEN+EX_R9(r13);	/* save r9, r10 */	\
-	std	r10,PACA_EXGEN+EX_R10(r13);				\
+	std	r9,PACA_EXGEN+EX_R9(r13);	/* save r9 */		\
+	HMT_MEDIUM_PPR_SAVE(PACA_EXGEN,r9);				\
+	std	r10,PACA_EXGEN+EX_R10(r13);	/* save r10 */		\
 	lbz	r10,PACASOFTIRQEN(r13);					\
 	mfcr	r9;							\
 	cmpwi	r10,0;							\
diff -Naurp linux5/arch/powerpc/kernel/entry_64.S linux6/arch/powerpc/kernel/entry_64.S
--- linux5/arch/powerpc/kernel/entry_64.S	2012-12-22 00:56:43.000000000 -0800
+++ linux6/arch/powerpc/kernel/entry_64.S	2012-12-22 01:51:32.000000000 -0800
@@ -240,6 +240,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECK
 
 	beq-	1f
 	ACCOUNT_CPU_USER_EXIT(r11, r12)
+	HMT_MEDIUM_LOW_HAS_PPR
 	ld	r13,GPR13(r1)	/* only restore r13 if returning to usermode */
 1:	ld	r2,GPR2(r1)
 	ld	r1,GPR1(r1)
@@ -313,6 +314,7 @@ syscall_exit_work:
 	subi	r12,r12,TI_FLAGS
 
 4:	/* Anything else left to do? */
+	SET_DEFAULT_THREAD_PPR(r3, r9)		/* Set thread.ppr = 3 */
 	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
 	beq	.ret_from_except_lite
 
@@ -661,6 +663,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_C
 	andi.	r0,r3,MSR_PR
 	beq	1f
 	ACCOUNT_CPU_USER_EXIT(r2, r4)
+	RESTORE_PPR(r2, r4)
 	REST_GPR(13, r1)
 1:
 	mtspr	SPRN_SRR1,r3
diff -Naurp linux5/arch/powerpc/kernel/exceptions-64s.S linux6/arch/powerpc/kernel/exceptions-64s.S
--- linux5/arch/powerpc/kernel/exceptions-64s.S	2012-12-22 00:56:43.000000000 -0800
+++ linux6/arch/powerpc/kernel/exceptions-64s.S	2012-12-22 03:05:13.000000000 -0800
@@ -39,7 +39,7 @@ __start_interrupts:
 
 	.globl system_reset_pSeries;
 system_reset_pSeries:
-	HMT_MEDIUM;
+	HMT_MEDIUM_PPR_DISCARD
 	DO_KVM	0x100;
 	SET_SCRATCH0(r13)
 #ifdef CONFIG_PPC_P7_NAP
@@ -69,7 +69,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206
 
 	. = 0x200
 _machine_check_pSeries:
-	HMT_MEDIUM
+	HMT_MEDIUM_PPR_DISCARD
 	DO_KVM	0x200
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
@@ -77,12 +77,13 @@ _machine_check_pSeries:
 	. = 0x300
 	.globl data_access_pSeries
 data_access_pSeries:
-	HMT_MEDIUM
+	HMT_MEDIUM_PPR_DISCARD
 	DO_KVM	0x300
 	SET_SCRATCH0(r13)
 BEGIN_FTR_SECTION
 	GET_PACA(r13)
 	std	r9,PACA_EXSLB+EX_R9(r13)
+	HMT_MEDIUM_PPR_SAVE(PACA_EXGEN, r9)
 	std	r10,PACA_EXSLB+EX_R10(r13)
 	mfspr	r10,SPRN_DAR
 	mfspr	r9,SPRN_DSISR
@@ -107,11 +108,12 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SL
 	. = 0x380
 	.globl data_access_slb_pSeries
 data_access_slb_pSeries:
-	HMT_MEDIUM
+	HMT_MEDIUM_PPR_DISCARD
 	DO_KVM	0x380
 	SET_SCRATCH0(r13)
 	GET_PACA(r13)
 	std	r3,PACA_EXSLB+EX_R3(r13)
+	HMT_MEDIUM_PPR_SAVE(PACA_EXSLB, r3)
 	mfspr	r3,SPRN_DAR
 	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
 	mfcr	r9
@@ -146,11 +148,12 @@ data_access_slb_pSeries:
 	. = 0x480
 	.globl instruction_access_slb_pSeries
 instruction_access_slb_pSeries:
-	HMT_MEDIUM
+	HMT_MEDIUM_PPR_DISCARD
 	DO_KVM	0x480
 	SET_SCRATCH0(r13)
 	GET_PACA(r13)
 	std	r3,PACA_EXSLB+EX_R3(r13)
+	HMT_MEDIUM_PPR_SAVE(PACA_EXSLB, r3)
 	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */
 	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
 	mfcr	r9
@@ -332,14 +335,14 @@ do_stab_bolted_pSeries:
 	.globl system_reset_fwnmi
       .align 7
 system_reset_fwnmi:
-	HMT_MEDIUM
+	HMT_MEDIUM_PPR_DISCARD
 	SET_SCRATCH0(r13)		/* save r13 */
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
 
 	.globl machine_check_fwnmi
       .align 7
 machine_check_fwnmi:
-	HMT_MEDIUM
+	HMT_MEDIUM_PPR_DISCARD
 	SET_SCRATCH0(r13)		/* save r13 */
 	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
 
@@ -648,6 +651,7 @@ BEGIN_FW_FTR_SECTION
 	mtspr	SPRN_SRR1,r12
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif /* CONFIG_PPC_ISERIES */
+	RESTORE_PPR_PACA(PACA_EXSLB, r9)
 	ld	r9,PACA_EXSLB+EX_R9(r13)
 	ld	r10,PACA_EXSLB+EX_R10(r13)
 	ld	r11,PACA_EXSLB+EX_R11(r13)
@@ -805,14 +809,11 @@ fast_exception_return:
 	andi.	r3,r12,MSR_RI		/* check if RI is set */
 	beq-	unrecov_fer
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	andi.	r3,r12,MSR_PR
 	beq	2f
 	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
-#endif
-
-	ld	r3,_CCR(r1)
+	RESTORE_PPR(r3, r4)
+2:	ld	r3,_CCR(r1)
 	ld	r4,_LINK(r1)
 	ld	r5,_CTR(r1)
 	ld	r6,_XER(r1)
