LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 03/10] powerpc/booke64: Fix exception numbers
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Scott Wood, Tiejun Chen, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

altivec_unavailable was commented as 0xf20 but the code uses 0x200.
Note that 0xf20 is also used by ap_unavailable.

altivec_assist was commented as 0x1700 but the code uses 0x220.

critical_input was commented as 0x580 but the code uses 0x100.

machine_check was commented and implemented as 0x200, which conflicts
with altivec_assist (it only builds because MC_EXCEPTION_PROLOG is
commented out).  Changed to the fixed IVOR value of 0x000.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/kernel/exceptions-64e.S | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 6772512..41380a4 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -299,8 +299,8 @@ exception_marker:
 	.balign	0x1000
 	.globl interrupt_base_book3e
 interrupt_base_book3e:					/* fake trap */
-	EXCEPTION_STUB(0x000, machine_check)		/* 0x0200 */
-	EXCEPTION_STUB(0x020, critical_input)		/* 0x0580 */
+	EXCEPTION_STUB(0x000, machine_check)
+	EXCEPTION_STUB(0x020, critical_input)		/* 0x0100 */
 	EXCEPTION_STUB(0x040, debug_crit)		/* 0x0d00 */
 	EXCEPTION_STUB(0x060, data_storage)		/* 0x0300 */
 	EXCEPTION_STUB(0x080, instruction_storage)	/* 0x0400 */
@@ -315,8 +315,8 @@ interrupt_base_book3e:					/* fake trap */
 	EXCEPTION_STUB(0x1a0, watchdog)			/* 0x09f0 */
 	EXCEPTION_STUB(0x1c0, data_tlb_miss)
 	EXCEPTION_STUB(0x1e0, instruction_tlb_miss)
-	EXCEPTION_STUB(0x200, altivec_unavailable)	/* 0x0f20 */
-	EXCEPTION_STUB(0x220, altivec_assist)		/* 0x1700 */
+	EXCEPTION_STUB(0x200, altivec_unavailable)
+	EXCEPTION_STUB(0x220, altivec_assist)
 	EXCEPTION_STUB(0x260, perfmon)
 	EXCEPTION_STUB(0x280, doorbell)
 	EXCEPTION_STUB(0x2a0, doorbell_crit)
@@ -343,9 +343,9 @@ interrupt_end_book3e:
 
 /* Machine Check Interrupt */
 	START_EXCEPTION(machine_check);
-	MC_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_MACHINE_CHECK,
+	MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK,
 			    PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
+//	EXCEPTION_COMMON(0x000, PACA_EXMC, INTS_DISABLE)
 //	bl	special_reg_save_mc
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
 //	CHECK_NAPPING();
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 04/10] powerpc/e6500: Make TLB lock recursive
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Scott Wood, Tiejun Chen, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

Once special level interrupts are supported, we may take nested TLB
misses -- so allow the same thread to acquire the lock recursively.

The lock will not be effective against the nested TLB miss handler
trying to write the same entry as the interrupted TLB miss handler, but
that's also a problem on non-threaded CPUs that lack TLB write
conditional.  This will be addressed in the patch that enables crit/mc
support by invalidating the TLB on return from level exceptions.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/include/asm/mmu-book3e.h |  9 ++++++---
 arch/powerpc/kernel/setup_64.c        |  2 ++
 arch/powerpc/mm/tlb_low_64e.S         | 19 ++++++++++++-------
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
index 89b785d..901dac6 100644
--- a/arch/powerpc/include/asm/mmu-book3e.h
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -287,11 +287,14 @@ extern int mmu_linear_psize;
 extern int mmu_vmemmap_psize;
 
 struct tlb_core_data {
+	/*
+	 * Per-core spinlock for e6500 TLB handlers (no tlbsrx.)
+	 * Must be the first struct element.
+	 */
+	u8 lock;
+
 	/* For software way selection, as on Freescale TLB1 */
 	u8 esel_next, esel_max, esel_first;
-
-	/* Per-core spinlock for e6500 TLB handlers (no tlbsrx.) */
-	u8 lock;
 };
 
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index da9c42f..4933909 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -102,6 +102,8 @@ static void setup_tlb_core_data(void)
 {
 	int cpu;
 
+	BUILD_BUG_ON(offsetof(struct tlb_core_data, lock) != 0);
+
 	for_each_possible_cpu(cpu) {
 		int first = cpu_first_thread_sibling(cpu);
 
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index 6bf5050..1e50249 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -284,7 +284,7 @@ itlb_miss_fault_bolted:
  * r14 = page table base
  * r13 = PACA
  * r11 = tlb_per_core ptr
- * r10 = crap (free to use)
+ * r10 = cpu number
  */
 tlb_miss_common_e6500:
 	/*
@@ -293,15 +293,18 @@ tlb_miss_common_e6500:
 	 *
 	 * MAS6:IND should be already set based on MAS4
 	 */
-	addi	r10,r11,TCD_LOCK
-1:	lbarx	r15,0,r10
+1:	lbarx	r15,0,r11
+	lhz	r10,PACAPACAINDEX(r13)
 	cmpdi	r15,0
+	cmpdi	cr1,r15,1	/* set cr1.eq = 0 for non-recursive */
 	bne	2f
-	li	r15,1
-	stbcx.	r15,0,r10
+	stbcx.	r10,0,r11
 	bne	1b
+3:
 	.subsection 1
-2:	lbz	r15,0(r10)
+2:	cmpd	cr1,r15,r10	/* recursive lock due to mcheck/crit/etc? */
+	beq	cr1,3b		/* unlock will happen if cr1.eq = 0 */
+	lbz	r15,0(r11)
 	cmpdi	r15,0
 	bne	2b
 	b	1b
@@ -379,9 +382,11 @@ tlb_miss_common_e6500:
 
 tlb_miss_done_e6500:
 	.macro	tlb_unlock_e6500
+	beq	cr1,1f		/* no unlock if lock was recursively grabbed */
 	li	r15,0
 	isync
-	stb	r15,TCD_LOCK(r11)
+	stb	r15,0(r11)
+1:
 	.endm
 
 	tlb_unlock_e6500
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 05/10] powerpc/booke64: Use SPRG7 for VDSO
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: kvm-ppc, Tiejun Chen, Paul Mackerras, Anton Blanchard, Scott Wood,
	Mihai Caraman, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

Previously SPRG3 was marked for use by both VDSO and critical
interrupts (though critical interrupts were not fully implemented).

In commit 8b64a9dfb091f1eca8b7e58da82f1e7d1d5fe0ad ("powerpc/booke64:
Use SPRG0/3 scratch for bolted TLB miss & crit int"), Mihai Caraman
made an attempt to resolve this conflict by restoring the VDSO value
early in the critical interrupt, but this has some issues:

 - It's incompatible with EXCEPTION_COMMON which restores r13 from the
   by-then-overwritten scratch (this cost me some debugging time).
 - It forces critical exceptions to be a special case handled
   differently from even machine check and debug level exceptions.
 - It didn't occur to me that it was possible to make this work at all
   (by doing a final "ld r13, PACA_EXCRIT+EX_R13(r13)") until after
   I made (most of) this patch. :-)

It might be worth investigating using a load rather than SPRG on return
from all exceptions (except TLB misses where the scratch never leaves
the SPRG) -- it could save a few cycles.  Until then, let's stick with
SPRG for all exceptions.

Since we cannot use SPRG4-7 for scratch without corrupting the state of
a KVM guest, move VDSO to SPRG7 on book3e.  Since neither SPRG4-7 nor
critical interrupts exist on book3s, SPRG3 is still used for VDSO
there.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Cc: Mihai Caraman <mihai.caraman@freescale.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: kvm-ppc@vger.kernel.org
---
 arch/powerpc/include/asm/exception-64e.h    |  5 ++---
 arch/powerpc/include/asm/kvm_booke_hv_asm.h |  9 +--------
 arch/powerpc/include/asm/paca.h             |  2 +-
 arch/powerpc/include/asm/reg.h              | 13 ++++++++++---
 arch/powerpc/kernel/asm-offsets.c           |  2 +-
 arch/powerpc/kernel/exceptions-64e.S        | 19 ++-----------------
 arch/powerpc/kernel/vdso.c                  |  8 ++++----
 arch/powerpc/kernel/vdso32/getcpu.S         |  2 +-
 arch/powerpc/kernel/vdso64/getcpu.S         |  2 +-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S     |  4 ++--
 arch/powerpc/kvm/book3s_interrupts.S        |  4 ++--
 arch/powerpc/kvm/bookehv_interrupts.S       | 10 ++++++----
 12 files changed, 33 insertions(+), 47 deletions(-)

diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index 51fa43e..e73452f 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -46,9 +46,8 @@
 #define EX_CR		(1 * 8)
 #define EX_R10		(2 * 8)
 #define EX_R11		(3 * 8)
-#define EX_R13		(4 * 8)
-#define EX_R14		(5 * 8)
-#define EX_R15		(6 * 8)
+#define EX_R14		(4 * 8)
+#define EX_R15		(5 * 8)
 
 /*
  * The TLB miss exception uses different slots.
diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
index 3a79f53..c3e3fd5 100644
--- a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
+++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -36,20 +36,13 @@
  *   *(r8 + GPR11) = saved r11
  *
  * 64-bit host
- * Expected inputs (GEN/GDBELL/DBG/MC exception types):
+ * Expected inputs (GEN/GDBELL/DBG/CRIT/MC exception types):
  *  r10 = saved CR
  *  r13 = PACA_POINTER
  *  *(r13 + PACA_EX##type + EX_R10) = saved r10
  *  *(r13 + PACA_EX##type + EX_R11) = saved r11
  *  SPRN_SPRG_##type##_SCRATCH = saved r13
  *
-  * Expected inputs (CRIT exception type):
- *  r10 = saved CR
- *  r13 = PACA_POINTER
- *  *(r13 + PACA_EX##type + EX_R10) = saved r10
- *  *(r13 + PACA_EX##type + EX_R11) = saved r11
- *  *(r13 + PACA_EX##type + EX_R13) = saved r13
- *
  * Expected inputs (TLB exception type):
  *  r10 = saved CR
  *  r13 = PACA_POINTER
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 9c5dbc3..948f01a 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -146,7 +146,7 @@ struct paca_struct {
 	u8 io_sync;			/* writel() needs spin_unlock sync */
 	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
 	u8 nap_state_lost;		/* NV GPR values lost in power7_idle */
-	u64 sprg3;			/* Saved user-visible sprg */
+	u64 sprg_vdso;			/* Saved user-visible sprg */
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	u64 tm_scratch;                 /* TM scratch area for reclaim */
 #endif
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 90c06ec..b9ac329 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -577,9 +577,13 @@
 #define SPRN_SPRG3	0x113	/* Special Purpose Register General 3 */
 #define SPRN_USPRG3	0x103	/* SPRG3 userspace read */
 #define SPRN_SPRG4	0x114	/* Special Purpose Register General 4 */
+#define SPRN_USPRG4	0x104	/* SPRG4 userspace read */
 #define SPRN_SPRG5	0x115	/* Special Purpose Register General 5 */
+#define SPRN_USPRG5	0x105	/* SPRG5 userspace read */
 #define SPRN_SPRG6	0x116	/* Special Purpose Register General 6 */
+#define SPRN_USPRG6	0x106	/* SPRG6 userspace read */
 #define SPRN_SPRG7	0x117	/* Special Purpose Register General 7 */
+#define SPRN_USPRG7	0x107	/* SPRG7 userspace read */
 #define SPRN_SRR0	0x01A	/* Save/Restore Register 0 */
 #define SPRN_SRR1	0x01B	/* Save/Restore Register 1 */
 #define   SRR1_ISI_NOPT		0x40000000 /* ISI: Not found in hash */
@@ -879,11 +883,10 @@
  * 64-bit embedded
  *	- SPRG0 generic exception scratch
  *	- SPRG2 TLB exception stack
- *	- SPRG3 critical exception scratch and
- *        CPU and NUMA node for VDSO getcpu (user visible)
+ *	- SPRG3 critical exception scratch (user visible, sorry!)
  *	- SPRG4 unused (user visible)
  *	- SPRG6 TLB miss scratch (user visible, sorry !)
- *	- SPRG7 critical exception scratch
+ *	- SPRG7 CPU and NUMA node for VDSO getcpu (user visible)
  *	- SPRG8 machine check exception scratch
  *	- SPRG9 debug exception scratch
  *
@@ -940,6 +943,8 @@
 #define SPRN_SPRG_SCRATCH0	SPRN_SPRG2
 #define SPRN_SPRG_HPACA		SPRN_HSPRG0
 #define SPRN_SPRG_HSCRATCH0	SPRN_HSPRG1
+#define SPRN_SPRG_VDSO_READ	SPRN_USPRG3
+#define SPRN_SPRG_VDSO_WRITE	SPRN_SPRG3
 
 #define GET_PACA(rX)					\
 	BEGIN_FTR_SECTION_NESTED(66);			\
@@ -983,6 +988,8 @@
 #define SPRN_SPRG_TLB_SCRATCH	SPRN_SPRG6
 #define SPRN_SPRG_GEN_SCRATCH	SPRN_SPRG0
 #define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH
+#define SPRN_SPRG_VDSO_READ	SPRN_USPRG7
+#define SPRN_SPRG_VDSO_WRITE	SPRN_SPRG7
 
 #define SET_PACA(rX)	mtspr	SPRN_SPRG_PACA,rX
 #define GET_PACA(rX)	mfspr	rX,SPRN_SPRG_PACA
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b5aacf7..dba8140 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -253,7 +253,7 @@ int main(void)
 	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
 	DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
 	DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
-	DEFINE(PACA_SPRG3, offsetof(struct paca_struct, sprg3));
+	DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso));
 #endif /* CONFIG_PPC64 */
 
 	/* RTAS */
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 41380a4..89e1133 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -55,7 +55,6 @@
 	mfspr	r13,SPRN_SPRG_PACA;	/* get PACA */			    \
 	std	r10,PACA_EX##type+EX_R10(r13);				    \
 	std	r11,PACA_EX##type+EX_R11(r13);				    \
-	PROLOG_STORE_RESTORE_SCRATCH_##type;				    \
 	mfcr	r10;			/* save CR */			    \
 	mfspr	r11,SPRN_##type##_SRR1;/* what are we coming from */	    \
 	DO_KVM	intnum,SPRN_##type##_SRR1;    /* KVM hook */		    \
@@ -116,20 +115,6 @@
 #define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)			    \
 	EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
 
-/*
- * Store user-visible scratch in PACA exception slots and restore proper value
- */
-#define PROLOG_STORE_RESTORE_SCRATCH_GEN
-#define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
-#define PROLOG_STORE_RESTORE_SCRATCH_DBG
-#define PROLOG_STORE_RESTORE_SCRATCH_MC
-
-#define PROLOG_STORE_RESTORE_SCRATCH_CRIT				    \
-	mfspr	r10,SPRN_SPRG_CRIT_SCRATCH;	/* get r13 */		    \
-	std	r10,PACA_EXCRIT+EX_R13(r13);				    \
-	ld	r11,PACA_SPRG3(r13);					    \
-	mtspr	SPRN_SPRG_CRIT_SCRATCH,r11;
-
 /* Variants of the "addition" argument for the prolog
  */
 #define PROLOG_ADDITION_NONE_GEN(n)
@@ -529,7 +514,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	mtcr	r10
 	ld	r10,PACA_EXCRIT+EX_R10(r13)	/* restore registers */
 	ld	r11,PACA_EXCRIT+EX_R11(r13)
-	ld	r13,PACA_EXCRIT+EX_R13(r13)
+	mfspr	r13,SPRN_SPRG_CRIT_SCRATCH
 	rfci
 
 	/* Normal debug exception */
@@ -542,7 +527,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	/* Now we mash up things to make it look like we are coming on a
 	 * normal exception
 	 */
-	ld	r15,PACA_EXCRIT+EX_R13(r13)
+	mfspr	r15,SPRN_SPRG_CRIT_SCRATCH
 	mtspr	SPRN_SPRG_GEN_SCRATCH,r15
 	mfspr	r14,SPRN_DBSR
 	EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 094e45c..ce74c33 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -715,8 +715,8 @@ int vdso_getcpu_init(void)
 	unsigned long cpu, node, val;
 
 	/*
-	 * SPRG3 contains the CPU in the bottom 16 bits and the NUMA node in
-	 * the next 16 bits. The VDSO uses this to implement getcpu().
+	 * SPRG_VDSO contains the CPU in the bottom 16 bits and the NUMA node
+	 * in the next 16 bits.  The VDSO uses this to implement getcpu().
 	 */
 	cpu = get_cpu();
 	WARN_ON_ONCE(cpu > 0xffff);
@@ -725,8 +725,8 @@ int vdso_getcpu_init(void)
 	WARN_ON_ONCE(node > 0xffff);
 
 	val = (cpu & 0xfff) | ((node & 0xffff) << 16);
-	mtspr(SPRN_SPRG3, val);
-	get_paca()->sprg3 = val;
+	mtspr(SPRN_SPRG_VDSO_WRITE, val);
+	get_paca()->sprg_vdso = val;
 
 	put_cpu();
 
diff --git a/arch/powerpc/kernel/vdso32/getcpu.S b/arch/powerpc/kernel/vdso32/getcpu.S
index 47afd08..23eb9a9 100644
--- a/arch/powerpc/kernel/vdso32/getcpu.S
+++ b/arch/powerpc/kernel/vdso32/getcpu.S
@@ -29,7 +29,7 @@
  */
 V_FUNCTION_BEGIN(__kernel_getcpu)
   .cfi_startproc
-	mfspr	r5,SPRN_USPRG3
+	mfspr	r5,SPRN_SPRG_VDSO_READ
 	cmpdi	cr0,r3,0
 	cmpdi	cr1,r4,0
 	clrlwi  r6,r5,16
diff --git a/arch/powerpc/kernel/vdso64/getcpu.S b/arch/powerpc/kernel/vdso64/getcpu.S
index 47afd08..23eb9a9 100644
--- a/arch/powerpc/kernel/vdso64/getcpu.S
+++ b/arch/powerpc/kernel/vdso64/getcpu.S
@@ -29,7 +29,7 @@
  */
 V_FUNCTION_BEGIN(__kernel_getcpu)
   .cfi_startproc
-	mfspr	r5,SPRN_USPRG3
+	mfspr	r5,SPRN_SPRG_VDSO_READ
 	cmpdi	cr0,r3,0
 	cmpdi	cr1,r4,0
 	clrlwi  r6,r5,16
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index e66d4ec..fbfca57 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -75,8 +75,8 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 
 	/* Restore SPRG3 */
-	ld	r3,PACA_SPRG3(r13)
-	mtspr	SPRN_SPRG3,r3
+	ld	r3,PACA_SPRG_VDSO(r13)
+	mtspr	SPRN_SPRG_VDSO_WRITE,r3
 
 	/* Reload the host's PMU registers */
 	ld	r3, PACALPPACAPTR(r13)	/* is the host using the PMU? */
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S
index f779450..3533c99 100644
--- a/arch/powerpc/kvm/book3s_interrupts.S
+++ b/arch/powerpc/kvm/book3s_interrupts.S
@@ -153,8 +153,8 @@ kvm_start_lightweight:
 	 * Reload kernel SPRG3 value.
 	 * No need to save guest value as usermode can't modify SPRG3.
 	 */
-	ld	r3, PACA_SPRG3(r13)
-	mtspr	SPRN_SPRG3, r3
+	ld	r3, PACA_SPRG_VDSO(r13)
+	mtspr	SPRN_SPRG_VDSO_WRITE, r3
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
 	/* R7 = vcpu */
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index e4185f6..99635a3 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -229,11 +229,7 @@
 	stw	r10, VCPU_CR(r4)
 	PPC_STL r11, VCPU_GPR(R4)(r4)
 	PPC_STL	r5, VCPU_GPR(R5)(r4)
-	.if \type == EX_CRIT
-	PPC_LL	r5, (\paca_ex + EX_R13)(r13)
-	.else
 	mfspr	r5, \scratch
-	.endif
 	PPC_STL	r6, VCPU_GPR(R6)(r4)
 	PPC_STL	r8, VCPU_GPR(R8)(r4)
 	PPC_STL	r9, VCPU_GPR(R9)(r4)
@@ -435,10 +431,16 @@ _GLOBAL(kvmppc_resume_host)
 	PPC_STL	r5, VCPU_LR(r4)
 	mfspr	r7, SPRN_SPRG5
 	stw	r3, VCPU_VRSAVE(r4)
+#ifdef CONFIG_64BIT
+	PPC_LL	r3, PACA_SPRG_VDSO(r13)
+#endif
 	PPC_STD(r6, VCPU_SHARED_SPRG4, r11)
 	mfspr	r8, SPRN_SPRG6
 	PPC_STD(r7, VCPU_SHARED_SPRG5, r11)
 	mfspr	r9, SPRN_SPRG7
+#ifdef CONFIG_64BIT
+	mtspr	SPRN_SPRG_VDSO_WRITE, r3
+#endif
 	PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
 	mfxer	r3
 	PPC_STD(r9, VCPU_SHARED_SPRG7, r11)
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 06/10] powerpc/booke64: Use SPRG_TLB_EXFRAME on bolted handlers
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: kvm-ppc, Tiejun Chen, Scott Wood, Mihai Caraman, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

While bolted handlers (including e6500) do not need to deal with a TLB
miss recursively causing another TLB miss, nested TLB misses can still
happen with crit/mc/debug exceptions -- so we still need to honor
SPRG_TLB_EXFRAME.

We don't need to spend time modifying it in the TLB miss fastpath,
though -- the special level exception will handle that.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Cc: Mihai Caraman <mihai.caraman@freescale.com>
Cc: kvm-ppc@vger.kernel.org
---
 arch/powerpc/include/asm/exception-64e.h    | 10 -------
 arch/powerpc/include/asm/kvm_booke_hv_asm.h |  8 ++++--
 arch/powerpc/kvm/bookehv_interrupts.S       | 14 +++++++--
 arch/powerpc/mm/tlb_low_64e.S               | 44 ++++++++++++++++++-----------
 4 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index e73452f..a563d9af 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -172,16 +172,6 @@ exc_##label##_book3e:
 	ld	r9,EX_TLB_R9(r12);					    \
 	ld	r8,EX_TLB_R8(r12);					    \
 	mtlr	r16;
-#define TLB_MISS_PROLOG_STATS_BOLTED						    \
-	mflr	r10;							    \
-	std	r8,PACA_EXTLB+EX_TLB_R8(r13);				    \
-	std	r9,PACA_EXTLB+EX_TLB_R9(r13);				    \
-	std	r10,PACA_EXTLB+EX_TLB_LR(r13);
-#define TLB_MISS_RESTORE_STATS_BOLTED					            \
-	ld	r16,PACA_EXTLB+EX_TLB_LR(r13);				    \
-	ld	r9,PACA_EXTLB+EX_TLB_R9(r13);				    \
-	ld	r8,PACA_EXTLB+EX_TLB_R8(r13);				    \
-	mtlr	r16;
 #define TLB_MISS_STATS_D(name)						    \
 	addi	r9,r13,MMSTAT_DSTATS+name;				    \
 	bl	.tlb_stat_inc;
diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
index c3e3fd5..e5f048b 100644
--- a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
+++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -45,10 +45,12 @@
  *
  * Expected inputs (TLB exception type):
  *  r10 = saved CR
+ *  r12 = extlb pointer
  *  r13 = PACA_POINTER
- *  *(r13 + PACA_EX##type + EX_TLB_R10) = saved r10
- *  *(r13 + PACA_EX##type + EX_TLB_R11) = saved r11
- *  SPRN_SPRG_GEN_SCRATCH = saved r13
+ *  *(r12 + EX_TLB_R10) = saved r10
+ *  *(r12 + EX_TLB_R11) = saved r11
+ *  *(r12 + EX_TLB_R13) = saved r13
+ *  SPRN_SPRG_GEN_SCRATCH = saved r12
  *
  * Only the bolted version of TLB miss exception handlers is supported now.
  */
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index 99635a3..890e338 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -229,13 +229,20 @@
 	stw	r10, VCPU_CR(r4)
 	PPC_STL r11, VCPU_GPR(R4)(r4)
 	PPC_STL	r5, VCPU_GPR(R5)(r4)
-	mfspr	r5, \scratch
 	PPC_STL	r6, VCPU_GPR(R6)(r4)
 	PPC_STL	r8, VCPU_GPR(R8)(r4)
 	PPC_STL	r9, VCPU_GPR(R9)(r4)
-	PPC_STL r5, VCPU_GPR(R13)(r4)
+	.if \type == EX_TLB
+	PPC_LL	r5, EX_TLB_R13(r12)
+	PPC_LL	r6, EX_TLB_R10(r12)
+	PPC_LL	r8, EX_TLB_R11(r12)
+	mfspr	r12, \scratch
+	.else
+	mfspr	r5, \scratch
 	PPC_LL	r6, (\paca_ex + \ex_r10)(r13)
 	PPC_LL	r8, (\paca_ex + \ex_r11)(r13)
+	.endif
+	PPC_STL r5, VCPU_GPR(R13)(r4)
 	PPC_STL r3, VCPU_GPR(R3)(r4)
 	PPC_STL r7, VCPU_GPR(R7)(r4)
 	PPC_STL r12, VCPU_GPR(R12)(r4)
@@ -444,6 +451,9 @@ _GLOBAL(kvmppc_resume_host)
 	PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
 	mfxer	r3
 	PPC_STD(r9, VCPU_SHARED_SPRG7, r11)
+#ifdef CONFIG_64BIT
+	mtspr	SPRN_SPRG_VDSO_WRITE, r3
+#endif
 
 	/* save guest MAS registers and restore host mas4 & mas6 */
 	mfspr	r5, SPRN_MAS0
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index 1e50249..356e8b4 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -39,37 +39,49 @@
  *                                                                    *
  **********************************************************************/
 
+/*
+ * Note that, unlike non-bolted handlers, TLB_EXFRAME is not
+ * modified by the TLB miss handlers themselves, since the TLB miss
+ * handler code will not itself cause a recursive TLB miss.
+ *
+ * TLB_EXFRAME will be modified when crit/mc/debug exceptions are
+ * entered/exited.
+ */
 .macro tlb_prolog_bolted intnum addr
-	mtspr	SPRN_SPRG_GEN_SCRATCH,r13
+	mtspr	SPRN_SPRG_GEN_SCRATCH,r12
+	mfspr	r12,SPRN_SPRG_TLB_EXFRAME
+	std	r13,EX_TLB_R13(r12)
+	std	r10,EX_TLB_R10(r12)
 	mfspr	r13,SPRN_SPRG_PACA
-	std	r10,PACA_EXTLB+EX_TLB_R10(r13)
+
 	mfcr	r10
-	std	r11,PACA_EXTLB+EX_TLB_R11(r13)
+	std	r11,EX_TLB_R11(r12)
 #ifdef CONFIG_KVM_BOOKE_HV
 BEGIN_FTR_SECTION
 	mfspr	r11, SPRN_SRR1
 END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
 #endif
 	DO_KVM	\intnum, SPRN_SRR1
-	std	r16,PACA_EXTLB+EX_TLB_R16(r13)
+	std	r16,EX_TLB_R16(r12)
 	mfspr	r16,\addr		/* get faulting address */
-	std	r14,PACA_EXTLB+EX_TLB_R14(r13)
+	std	r14,EX_TLB_R14(r12)
 	ld	r14,PACAPGD(r13)
-	std	r15,PACA_EXTLB+EX_TLB_R15(r13)
-	std	r10,PACA_EXTLB+EX_TLB_CR(r13)
-	TLB_MISS_PROLOG_STATS_BOLTED
+	std	r15,EX_TLB_R15(r12)
+	std	r10,EX_TLB_CR(r12)
+	TLB_MISS_PROLOG_STATS
 .endm
 
 .macro tlb_epilog_bolted
-	ld	r14,PACA_EXTLB+EX_TLB_CR(r13)
-	ld	r10,PACA_EXTLB+EX_TLB_R10(r13)
-	ld	r11,PACA_EXTLB+EX_TLB_R11(r13)
+	ld	r14,EX_TLB_CR(r12)
+	ld	r10,EX_TLB_R10(r12)
+	ld	r11,EX_TLB_R11(r12)
+	ld	r13,EX_TLB_R13(r12)
 	mtcr	r14
-	ld	r14,PACA_EXTLB+EX_TLB_R14(r13)
-	ld	r15,PACA_EXTLB+EX_TLB_R15(r13)
-	TLB_MISS_RESTORE_STATS_BOLTED
-	ld	r16,PACA_EXTLB+EX_TLB_R16(r13)
-	mfspr	r13,SPRN_SPRG_GEN_SCRATCH
+	ld	r14,EX_TLB_R14(r12)
+	ld	r15,EX_TLB_R15(r12)
+	TLB_MISS_RESTORE_STATS
+	ld	r16,EX_TLB_R16(r12)
+	mfspr	r12,SPRN_SPRG_GEN_SCRATCH
 .endm
 
 /* Data TLB miss */
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 07/10] powerpc/booke64: Remove ints from EXCEPTION_COMMON
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Scott Wood, Tiejun Chen, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

The ints parameter was used to optionally insert RECONCILE_IRQ_STATE
into EXCEPTION_COMMON.  However, since it came at the end of
EXCEPTION_COMMON, there was no real benefit for it to be there as
opposed to being called separately by the caller of EXCEPTION_COMMON.

The ints parameter was causing some hassle when trying to add an extra
macro layer.  Besides avoiding that, moving "ints" to the caller makes
the code simpler by:
 - avoiding the asymmetry where INTS_RESTORE_HARD is called separately
by the individual exception, but INTS_DISABLE was not
 - removing the no-op INTS_KEEP
 - not having an unnecessary macro parameter

It also turned out to be necessary to delay the INTS_DISABLE
in the case of special level exceptions until after we saved the
old value of PACAIRQHAPPENED.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/kernel/exceptions-64e.S | 82 ++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 36 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 89e1133..0204c39 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -151,7 +151,7 @@
 /* Core exception code for all exceptions except TLB misses.
  * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
  */
-#define EXCEPTION_COMMON(n, excf, ints)					    \
+#define EXCEPTION_COMMON(n, excf)					    \
 exc_##n##_common:							    \
 	std	r0,GPR0(r1);		/* save r0 in stackframe */	    \
 	std	r2,GPR2(r1);		/* save r2 in stackframe */	    \
@@ -188,24 +188,20 @@ exc_##n##_common:							    \
 	std	r11,SOFTE(r1);		/* and save it to stackframe */     \
 	std	r12,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */	    \
 	std	r3,_TRAP(r1);		/* set trap number		*/  \
-	std	r0,RESULT(r1);		/* clear regs->result */	    \
-	ints;
+	std	r0,RESULT(r1);		/* clear regs->result */
 
-/* Variants for the "ints" argument. This one does nothing when we want
- * to keep interrupts in their original state
- */
-#define INTS_KEEP
-
-/* This second version is meant for exceptions that don't immediately
- * hard-enable. We set a bit in paca->irq_happened to ensure that
- * a subsequent call to arch_local_irq_restore() will properly
- * hard-enable and avoid the fast-path, and then reconcile irq state.
+/*
+ * This is meant for exceptions that don't immediately hard-enable.  We
+ * set a bit in paca->irq_happened to ensure that a subsequent call to
+ * arch_local_irq_restore() will properly hard-enable and avoid the
+ * fast-path, and then reconcile irq state.
  */
 #define INTS_DISABLE	RECONCILE_IRQ_STATE(r3,r4)
 
-/* This is called by exceptions that used INTS_KEEP (that did not touch
- * irq indicators in the PACA). This will restore MSR:EE to it's previous
- * value
+/*
+ * This is called by exceptions that don't use INTS_DISABLE (that did not
+ * touch irq indicators in the PACA).  This will restore MSR:EE to it's
+ * previous value
  *
  * XXX In the long run, we may want to open-code it in order to separate the
  *     load from the wrtee, thus limiting the latency caused by the dependency
@@ -263,7 +259,8 @@ exc_##n##_bad_stack:							    \
 #define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)		\
 	START_EXCEPTION(label);						\
 	NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
-	EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE)		\
+	EXCEPTION_COMMON(trapnum, PACA_EXGEN)				\
+	INTS_DISABLE;							\
 	ack(r8);							\
 	CHECK_NAPPING();						\
 	addi	r3,r1,STACK_FRAME_OVERHEAD;				\
@@ -318,7 +315,8 @@ interrupt_end_book3e:
 	START_EXCEPTION(critical_input);
 	CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
+//	EXCEPTION_COMMON(0x100, PACA_EXCRIT)
+//	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -330,7 +328,8 @@ interrupt_end_book3e:
 	START_EXCEPTION(machine_check);
 	MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK,
 			    PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x000, PACA_EXMC, INTS_DISABLE)
+//	EXCEPTION_COMMON(0x000, PACA_EXMC)
+//	INTS_DISABLE
 //	bl	special_reg_save_mc
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
 //	CHECK_NAPPING();
@@ -344,7 +343,8 @@ interrupt_end_book3e:
 				PROLOG_ADDITION_2REGS)
 	mfspr	r14,SPRN_DEAR
 	mfspr	r15,SPRN_ESR
-	EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
+	EXCEPTION_COMMON(0x300, PACA_EXGEN)
+	INTS_DISABLE
 	b	storage_fault_common
 
 /* Instruction Storage Interrupt */
@@ -353,7 +353,8 @@ interrupt_end_book3e:
 				PROLOG_ADDITION_2REGS)
 	li	r15,0
 	mr	r14,r10
-	EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
+	EXCEPTION_COMMON(0x400, PACA_EXGEN)
+	INTS_DISABLE
 	b	storage_fault_common
 
 /* External Input Interrupt */
@@ -366,7 +367,7 @@ interrupt_end_book3e:
 				PROLOG_ADDITION_2REGS)
 	mfspr	r14,SPRN_DEAR
 	mfspr	r15,SPRN_ESR
-	EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x600, PACA_EXGEN)
 	b	alignment_more	/* no room, go out of line */
 
 /* Program Interrupt */
@@ -374,7 +375,8 @@ interrupt_end_book3e:
 	NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
 				PROLOG_ADDITION_1REG)
 	mfspr	r14,SPRN_ESR
-	EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
+	EXCEPTION_COMMON(0x700, PACA_EXGEN)
+	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	ld	r14,PACA_EXGEN+EX_R14(r13)
@@ -387,7 +389,7 @@ interrupt_end_book3e:
 	NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
 				PROLOG_ADDITION_NONE)
 	/* we can probably do a shorter exception entry for that one... */
-	EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x800, PACA_EXGEN)
 	ld	r12,_MSR(r1)
 	andi.	r0,r12,MSR_PR;
 	beq-	1f
@@ -404,7 +406,7 @@ interrupt_end_book3e:
 	NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL,
 				PROLOG_ADDITION_NONE)
 	/* we can probably do a shorter exception entry for that one... */
-	EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x200, PACA_EXGEN)
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
 	ld	r12,_MSR(r1)
@@ -426,7 +428,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	NORMAL_EXCEPTION_PROLOG(0x220,
 				BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST,
 				PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE)
+	EXCEPTION_COMMON(0x220, PACA_EXGEN)
+	INTS_DISABLE
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 #ifdef CONFIG_ALTIVEC
@@ -451,7 +454,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	START_EXCEPTION(watchdog);
 	CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
+//	EXCEPTION_COMMON(0x9f0, PACA_EXCRIT)
+//	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -471,7 +475,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	START_EXCEPTION(ap_unavailable);
 	NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
 				PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
+	EXCEPTION_COMMON(0xf20, PACA_EXGEN)
+	INTS_DISABLE
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.unknown_exception
@@ -530,7 +535,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	mfspr	r15,SPRN_SPRG_CRIT_SCRATCH
 	mtspr	SPRN_SPRG_GEN_SCRATCH,r15
 	mfspr	r14,SPRN_DBSR
-	EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
+	EXCEPTION_COMMON(0xd00, PACA_EXCRIT)
+	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	mr	r4,r14
@@ -596,7 +602,8 @@ kernel_dbg_exc:
 	mfspr	r15,SPRN_SPRG_DBG_SCRATCH
 	mtspr	SPRN_SPRG_GEN_SCRATCH,r15
 	mfspr	r14,SPRN_DBSR
-	EXCEPTION_COMMON(0xd08, PACA_EXDBG, INTS_DISABLE)
+	EXCEPTION_COMMON(0xd08, PACA_EXDBG)
+	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	mr	r4,r14
@@ -609,7 +616,8 @@ kernel_dbg_exc:
 	START_EXCEPTION(perfmon);
 	NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
 				PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
+	EXCEPTION_COMMON(0x260, PACA_EXGEN)
+	INTS_DISABLE
 	CHECK_NAPPING()
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.performance_monitor_exception
@@ -623,7 +631,8 @@ kernel_dbg_exc:
 	START_EXCEPTION(doorbell_crit);
 	CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
+//	EXCEPTION_COMMON(0x2a0, PACA_EXCRIT)
+//	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -638,7 +647,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(guest_doorbell);
 	GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x2c0, PACA_EXGEN)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
@@ -649,7 +658,8 @@ kernel_dbg_exc:
 	START_EXCEPTION(guest_doorbell_crit);
 	CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
+//	EXCEPTION_COMMON(0x2e0, PACA_EXCRIT)
+//	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -661,7 +671,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(hypercall);
 	NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x310, PACA_EXGEN)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
@@ -672,7 +682,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(ehpriv);
 	NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x320, PACA_EXGEN)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
@@ -683,7 +693,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(lrat_error);
 	NORMAL_EXCEPTION_PROLOG(0x340, BOOKE_INTERRUPT_LRAT_ERROR,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x340, PACA_EXGEN, INTS_KEEP)
+	EXCEPTION_COMMON(0x340, PACA_EXGEN)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 08/10] powerpc/booke64: Add crit/mc/debug support to EXCEPTION_COMMON
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Scott Wood, Tiejun Chen, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

Use the proper scratch SPRG and PACA region.  Introduce level-specific
macros to simplify usage and avoid needing to do a bunch of token
pasting throughout EXCEPTION_COMMON().

Now that EXCEPTION_COMMON_DBG() is properly using the debug scratch
register, there's no more need for the caller to move the value to the
GEN scratch first.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/kernel/exceptions-64e.S | 63 +++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 0204c39..2beb5bd 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -148,10 +148,8 @@
 	std	r15,PACA_EXMC+EX_R15(r13)
 
 
-/* Core exception code for all exceptions except TLB misses.
- * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
- */
-#define EXCEPTION_COMMON(n, excf)					    \
+/* Core exception code for all exceptions except TLB misses. */
+#define EXCEPTION_COMMON_LVL(n, scratch, excf)				    \
 exc_##n##_common:							    \
 	std	r0,GPR0(r1);		/* save r0 in stackframe */	    \
 	std	r2,GPR2(r1);		/* save r2 in stackframe */	    \
@@ -164,7 +162,7 @@ exc_##n##_common:							    \
 	ACCOUNT_CPU_USER_ENTRY(r10,r11);/* accounting (uses cr0+eq) */	    \
 2:	ld	r3,excf+EX_R10(r13);	/* get back r10 */		    \
 	ld	r4,excf+EX_R11(r13);	/* get back r11 */		    \
-	mfspr	r5,SPRN_SPRG_GEN_SCRATCH;/* get back r13 */		    \
+	mfspr	r5,scratch;		/* get back r13 */		    \
 	std	r12,GPR12(r1);		/* save r12 in stackframe */	    \
 	ld	r2,PACATOC(r13);	/* get kernel TOC into r2 */	    \
 	mflr	r6;			/* save LR in stackframe */	    \
@@ -190,6 +188,15 @@ exc_##n##_common:							    \
 	std	r3,_TRAP(r1);		/* set trap number		*/  \
 	std	r0,RESULT(r1);		/* clear regs->result */
 
+#define EXCEPTION_COMMON(n) \
+	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_GEN_SCRATCH, PACA_EXGEN)
+#define EXCEPTION_COMMON_CRIT(n) \
+	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_CRIT_SCRATCH, PACA_EXCRIT)
+#define EXCEPTION_COMMON_MC(n) \
+	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_MC_SCRATCH, PACA_EXMC)
+#define EXCEPTION_COMMON_DBG(n) \
+	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_DBG_SCRATCH, PACA_EXDBG)
+
 /*
  * This is meant for exceptions that don't immediately hard-enable.  We
  * set a bit in paca->irq_happened to ensure that a subsequent call to
@@ -259,7 +266,7 @@ exc_##n##_bad_stack:							    \
 #define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)		\
 	START_EXCEPTION(label);						\
 	NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
-	EXCEPTION_COMMON(trapnum, PACA_EXGEN)				\
+	EXCEPTION_COMMON(trapnum)					\
 	INTS_DISABLE;							\
 	ack(r8);							\
 	CHECK_NAPPING();						\
@@ -315,7 +322,7 @@ interrupt_end_book3e:
 	START_EXCEPTION(critical_input);
 	CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x100, PACA_EXCRIT)
+//	EXCEPTION_COMMON_CRIT(0x100)
 //	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -328,7 +335,7 @@ interrupt_end_book3e:
 	START_EXCEPTION(machine_check);
 	MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK,
 			    PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x000, PACA_EXMC)
+//	EXCEPTION_COMMON_MC(0x000)
 //	INTS_DISABLE
 //	bl	special_reg_save_mc
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -343,7 +350,7 @@ interrupt_end_book3e:
 				PROLOG_ADDITION_2REGS)
 	mfspr	r14,SPRN_DEAR
 	mfspr	r15,SPRN_ESR
-	EXCEPTION_COMMON(0x300, PACA_EXGEN)
+	EXCEPTION_COMMON(0x300)
 	INTS_DISABLE
 	b	storage_fault_common
 
@@ -353,7 +360,7 @@ interrupt_end_book3e:
 				PROLOG_ADDITION_2REGS)
 	li	r15,0
 	mr	r14,r10
-	EXCEPTION_COMMON(0x400, PACA_EXGEN)
+	EXCEPTION_COMMON(0x400)
 	INTS_DISABLE
 	b	storage_fault_common
 
@@ -367,7 +374,7 @@ interrupt_end_book3e:
 				PROLOG_ADDITION_2REGS)
 	mfspr	r14,SPRN_DEAR
 	mfspr	r15,SPRN_ESR
-	EXCEPTION_COMMON(0x600, PACA_EXGEN)
+	EXCEPTION_COMMON(0x600)
 	b	alignment_more	/* no room, go out of line */
 
 /* Program Interrupt */
@@ -375,7 +382,7 @@ interrupt_end_book3e:
 	NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
 				PROLOG_ADDITION_1REG)
 	mfspr	r14,SPRN_ESR
-	EXCEPTION_COMMON(0x700, PACA_EXGEN)
+	EXCEPTION_COMMON(0x700)
 	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -389,7 +396,7 @@ interrupt_end_book3e:
 	NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
 				PROLOG_ADDITION_NONE)
 	/* we can probably do a shorter exception entry for that one... */
-	EXCEPTION_COMMON(0x800, PACA_EXGEN)
+	EXCEPTION_COMMON(0x800)
 	ld	r12,_MSR(r1)
 	andi.	r0,r12,MSR_PR;
 	beq-	1f
@@ -406,7 +413,7 @@ interrupt_end_book3e:
 	NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL,
 				PROLOG_ADDITION_NONE)
 	/* we can probably do a shorter exception entry for that one... */
-	EXCEPTION_COMMON(0x200, PACA_EXGEN)
+	EXCEPTION_COMMON(0x200)
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
 	ld	r12,_MSR(r1)
@@ -428,7 +435,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	NORMAL_EXCEPTION_PROLOG(0x220,
 				BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST,
 				PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x220, PACA_EXGEN)
+	EXCEPTION_COMMON(0x220)
 	INTS_DISABLE
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -454,7 +461,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	START_EXCEPTION(watchdog);
 	CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x9f0, PACA_EXCRIT)
+//	EXCEPTION_COMMON_CRIT(0x9f0)
 //	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -475,7 +482,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	START_EXCEPTION(ap_unavailable);
 	NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
 				PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0xf20, PACA_EXGEN)
+	EXCEPTION_COMMON(0xf20)
 	INTS_DISABLE
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -532,10 +539,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	/* Now we mash up things to make it look like we are coming on a
 	 * normal exception
 	 */
-	mfspr	r15,SPRN_SPRG_CRIT_SCRATCH
-	mtspr	SPRN_SPRG_GEN_SCRATCH,r15
 	mfspr	r14,SPRN_DBSR
-	EXCEPTION_COMMON(0xd00, PACA_EXCRIT)
+	EXCEPTION_COMMON_CRIT(0xd00)
 	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -599,10 +604,8 @@ kernel_dbg_exc:
 	/* Now we mash up things to make it look like we are coming on a
 	 * normal exception
 	 */
-	mfspr	r15,SPRN_SPRG_DBG_SCRATCH
-	mtspr	SPRN_SPRG_GEN_SCRATCH,r15
 	mfspr	r14,SPRN_DBSR
-	EXCEPTION_COMMON(0xd08, PACA_EXDBG)
+	EXCEPTION_COMMON_DBG(0xd08)
 	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -616,7 +619,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(perfmon);
 	NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
 				PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x260, PACA_EXGEN)
+	EXCEPTION_COMMON(0x260)
 	INTS_DISABLE
 	CHECK_NAPPING()
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -631,7 +634,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(doorbell_crit);
 	CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x2a0, PACA_EXCRIT)
+//	EXCEPTION_COMMON_CRIT(0x2a0)
 //	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -647,7 +650,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(guest_doorbell);
 	GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x2c0, PACA_EXGEN)
+	EXCEPTION_COMMON(0x2c0)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
@@ -658,7 +661,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(guest_doorbell_crit);
 	CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON(0x2e0, PACA_EXCRIT)
+//	EXCEPTION_COMMON_CRIT(0x2e0)
 //	INTS_DISABLE
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -671,7 +674,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(hypercall);
 	NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x310, PACA_EXGEN)
+	EXCEPTION_COMMON(0x310)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
@@ -682,7 +685,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(ehpriv);
 	NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x320, PACA_EXGEN)
+	EXCEPTION_COMMON(0x320)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
@@ -693,7 +696,7 @@ kernel_dbg_exc:
 	START_EXCEPTION(lrat_error);
 	NORMAL_EXCEPTION_PROLOG(0x340, BOOKE_INTERRUPT_LRAT_ERROR,
 			        PROLOG_ADDITION_NONE)
-	EXCEPTION_COMMON(0x340, PACA_EXGEN)
+	EXCEPTION_COMMON(0x340)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
 	INTS_RESTORE_HARD
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 09/10] powerpc/booke64: Critical and machine check exception support
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Scott Wood, Tiejun Chen, linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

Add special state saving for critical and machine check exceptions.

Most of this code could be used to handle debug exceptions taken from
kernel space, but actually doing so is outside the scope of this patch.

The various critical and machine check exceptions now point to their
real handlers, rather than hanging the kernel.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/include/asm/paca.h      |   7 +-
 arch/powerpc/kernel/exceptions-64e.S | 343 +++++++++++++++++++++++++++++------
 arch/powerpc/mm/tlb_nohash.c         |  11 ++
 3 files changed, 300 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 948f01a..8e956a0 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -116,8 +116,11 @@ struct paca_struct {
 	/* Shared by all threads of a core -- points to tcd of first thread */
 	struct tlb_core_data *tcd_ptr;
 
-	/* We can have up to 3 levels of reentrancy in the TLB miss handler */
-	u64 extlb[3][EX_TLB_SIZE / sizeof(u64)];
+	/*
+	 * We can have up to 3 levels of reentrancy in the TLB miss handler,
+	 * in each of four exception levels (normal, crit, mcheck, debug).
+	 */
+	u64 extlb[12][EX_TLB_SIZE / sizeof(u64)];
 	u64 exmc[8];		/* used for machine checks */
 	u64 excrit[8];		/* used for crit interrupts */
 	u64 exdbg[8];		/* used for debug interrupts */
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 2beb5bd..c1bee3c 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -34,20 +34,250 @@
  *     special interrupts from within a non-standard level will probably
  *     blow you up
  */
-#define	SPECIAL_EXC_FRAME_SIZE	INT_FRAME_SIZE
+#define SPECIAL_EXC_SRR0	0
+#define SPECIAL_EXC_SRR1	1
+#define SPECIAL_EXC_SPRG_GEN	2
+#define SPECIAL_EXC_SPRG_TLB	3
+#define SPECIAL_EXC_MAS0	4
+#define SPECIAL_EXC_MAS1	5
+#define SPECIAL_EXC_MAS2	6
+#define SPECIAL_EXC_MAS3	7
+#define SPECIAL_EXC_MAS6	8
+#define SPECIAL_EXC_MAS7	9
+#define SPECIAL_EXC_MAS5	10	/* E.HV only */
+#define SPECIAL_EXC_MAS8	11	/* E.HV only */
+#define SPECIAL_EXC_IRQHAPPENED	12
+#define SPECIAL_EXC_DEAR	13
+#define SPECIAL_EXC_ESR		14
+#define SPECIAL_EXC_SOFTE	15
+#define SPECIAL_EXC_CSRR0	16
+#define SPECIAL_EXC_CSRR1	17
+/* must be even to keep 16-byte stack alignment */
+#define SPECIAL_EXC_END		18
+
+#define SPECIAL_EXC_FRAME_SIZE	(INT_FRAME_SIZE + SPECIAL_EXC_END * 8)
+#define SPECIAL_EXC_FRAME_OFFS  (INT_FRAME_SIZE - 288)
+
+#define SPECIAL_EXC_STORE(reg, name) \
+	std	reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1)
+
+#define SPECIAL_EXC_LOAD(reg, name) \
+	ld	reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1)
+
+special_reg_save:
+	lbz	r9,PACAIRQHAPPENED(r13)
+	RECONCILE_IRQ_STATE(r3,r4)
 
-/* Now we only store something to exception thread info */
-#define	EXC_LEVEL_EXCEPTION_PROLOG(type)				\
-	ld	r14,PACAKSAVE(r13);					\
-	CURRENT_THREAD_INFO(r14, r14);					\
-	CURRENT_THREAD_INFO(r15, r1);					\
-	ld	r10,TI_FLAGS(r14);		     			\
-	std	r10,TI_FLAGS(r15);			     		\
-	ld	r10,TI_PREEMPT(r14);		     			\
-	std	r10,TI_PREEMPT(r15);		     			\
-	ld	r10,TI_TASK(r14);			     		\
-	std	r10,TI_TASK(r15);
+	/*
+	 * We only need (or have stack space) to save this stuff if
+	 * we interrupted the kernel.
+	 */
+	ld	r3,_MSR(r1)
+	andi.	r3,r3,MSR_PR
+	bnelr
+
+	/* Copy info into temporary exception thread info */
+	ld	r11,PACAKSAVE(r13)
+	CURRENT_THREAD_INFO(r11, r11)
+	CURRENT_THREAD_INFO(r12, r1)
+	ld	r10,TI_FLAGS(r11)
+	std	r10,TI_FLAGS(r12)
+	ld	r10,TI_PREEMPT(r11)
+	std	r10,TI_PREEMPT(r12)
+	ld	r10,TI_TASK(r11)
+	std	r10,TI_TASK(r12)
+
+	/*
+	 * Advance to the next TLB exception frame for handler
+	 * types that don't do it automatically.
+	 */
+	LOAD_REG_ADDR(r11,extlb_level_exc)
+	lwz	r12,0(r11)
+	mfspr	r10,SPRN_SPRG_TLB_EXFRAME
+	add	r10,r10,r12
+	mtspr	SPRN_SPRG_TLB_EXFRAME,r10
+
+	/*
+	 * Save registers needed to allow nesting of certain exceptions
+	 * (such as TLB misses) inside special exception levels
+	 */
+	mfspr	r10,SPRN_SRR0
+	SPECIAL_EXC_STORE(r10,SRR0)
+	mfspr	r10,SPRN_SRR1
+	SPECIAL_EXC_STORE(r10,SRR1)
+	mfspr	r10,SPRN_SPRG_GEN_SCRATCH
+	SPECIAL_EXC_STORE(r10,SPRG_GEN)
+	mfspr	r10,SPRN_SPRG_TLB_SCRATCH
+	SPECIAL_EXC_STORE(r10,SPRG_TLB)
+	mfspr	r10,SPRN_MAS0
+	SPECIAL_EXC_STORE(r10,MAS0)
+	mfspr	r10,SPRN_MAS1
+	SPECIAL_EXC_STORE(r10,MAS1)
+	mfspr	r10,SPRN_MAS2
+	SPECIAL_EXC_STORE(r10,MAS2)
+	mfspr	r10,SPRN_MAS3
+	SPECIAL_EXC_STORE(r10,MAS3)
+	mfspr	r10,SPRN_MAS6
+	SPECIAL_EXC_STORE(r10,MAS6)
+	mfspr	r10,SPRN_MAS7
+	SPECIAL_EXC_STORE(r10,MAS7)
+BEGIN_FTR_SECTION
+	mfspr	r10,SPRN_MAS5
+	SPECIAL_EXC_STORE(r10,MAS5)
+	mfspr	r10,SPRN_MAS8
+	SPECIAL_EXC_STORE(r10,MAS8)
+
+	/* MAS5/8 could have inappropriate values if we interrupted KVM code */
+	li	r10,0
+	mtspr	SPRN_MAS5,r10
+	mtspr	SPRN_MAS8,r10
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+	SPECIAL_EXC_STORE(r9,IRQHAPPENED)
+
+	mfspr	r10,SPRN_DEAR
+	SPECIAL_EXC_STORE(r10,DEAR)
+	mfspr	r10,SPRN_ESR
+	SPECIAL_EXC_STORE(r10,ESR)
+
+	lbz	r10,PACASOFTIRQEN(r13)
+	SPECIAL_EXC_STORE(r10,SOFTE)
+	ld	r10,_NIP(r1)
+	SPECIAL_EXC_STORE(r10,CSRR0)
+	ld	r10,_MSR(r1)
+	SPECIAL_EXC_STORE(r10,CSRR1)
+
+	blr
+
+ret_from_level_except:
+	ld	r3,_MSR(r1)
+	andi.	r3,r3,MSR_PR
+	beq	1f
+	b	ret_from_except
+1:
+
+	LOAD_REG_ADDR(r11,extlb_level_exc)
+	lwz	r12,0(r11)
+	mfspr	r10,SPRN_SPRG_TLB_EXFRAME
+	sub	r10,r10,r12
+	mtspr	SPRN_SPRG_TLB_EXFRAME,r10
+
+	/*
+	 * It's possible that the special level exception interrupted a
+	 * TLB miss handler, and inserted the same entry that the
+	 * interrupted handler was about to insert.  On CPUs without TLB
+	 * write conditional, this can result in a duplicate TLB entry.
+	 * Wipe all non-bolted entries to be safe.
+	 *
+	 * Note that this doesn't protect against any TLB misses
+	 * we may take accessing the stack from here to the end of
+	 * the special level exception.  It's not clear how we can
+	 * reasonably protect against that, but only CPUs with
+	 * neither TLB write conditional nor bolted kernel memory
+	 * are affected.  Do any such CPUs even exist?
+	 */
+	PPC_TLBILX_ALL(0,R0)
+
+	REST_NVGPRS(r1)
+
+	SPECIAL_EXC_LOAD(r10,SRR0)
+	mtspr	SPRN_SRR0,r10
+	SPECIAL_EXC_LOAD(r10,SRR1)
+	mtspr	SPRN_SRR1,r10
+	SPECIAL_EXC_LOAD(r10,SPRG_GEN)
+	mtspr	SPRN_SPRG_GEN_SCRATCH,r10
+	SPECIAL_EXC_LOAD(r10,SPRG_TLB)
+	mtspr	SPRN_SPRG_TLB_SCRATCH,r10
+	SPECIAL_EXC_LOAD(r10,MAS0)
+	mtspr	SPRN_MAS0,r10
+	SPECIAL_EXC_LOAD(r10,MAS1)
+	mtspr	SPRN_MAS1,r10
+	SPECIAL_EXC_LOAD(r10,MAS2)
+	mtspr	SPRN_MAS2,r10
+	SPECIAL_EXC_LOAD(r10,MAS3)
+	mtspr	SPRN_MAS3,r10
+	SPECIAL_EXC_LOAD(r10,MAS6)
+	mtspr	SPRN_MAS6,r10
+	SPECIAL_EXC_LOAD(r10,MAS7)
+	mtspr	SPRN_MAS7,r10
+BEGIN_FTR_SECTION
+	SPECIAL_EXC_LOAD(r10,MAS5)
+	mtspr	SPRN_MAS5,r10
+	SPECIAL_EXC_LOAD(r10,MAS8)
+	mtspr	SPRN_MAS8,r10
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+
+	lbz	r6,PACASOFTIRQEN(r13)
+	ld	r5,SOFTE(r1)
+
+	/* Interrupts had better not already be enabled... */
+	twnei	r6,0
+
+	cmpwi	cr0,r5,0
+	beq	1f
 
+	TRACE_ENABLE_INTS
+	stb	r5,PACASOFTIRQEN(r13)
+1:
+	/*
+	 * Restore PACAIRQHAPPENED rather than setting it based on
+	 * the return MSR[EE], since we could have interrupted
+	 * __check_irq_replay() or other inconsistent transitory
+	 * states that must remain that way.
+	 */
+	SPECIAL_EXC_LOAD(r10,IRQHAPPENED)
+	stb	r10,PACAIRQHAPPENED(r13)
+
+	SPECIAL_EXC_LOAD(r10,DEAR)
+	mtspr	SPRN_DEAR,r10
+	SPECIAL_EXC_LOAD(r10,ESR)
+	mtspr	SPRN_ESR,r10
+
+	stdcx.	r0,0,r1		/* to clear the reservation */
+
+	REST_4GPRS(2, r1)
+	REST_4GPRS(6, r1)
+
+	ld	r10,_CTR(r1)
+	ld	r11,_XER(r1)
+	mtctr	r10
+	mtxer	r11
+
+	blr
+
+.macro ret_from_level srr0 srr1 paca_ex scratch
+	bl	ret_from_level_except
+
+	ld	r10,_LINK(r1)
+	ld	r11,_CCR(r1)
+	ld	r0,GPR13(r1)
+	mtlr	r10
+	mtcr	r11
+
+	ld	r10,GPR10(r1)
+	ld	r11,GPR11(r1)
+	ld	r12,GPR12(r1)
+	mtspr	\scratch,r0
+
+	std	r10,\paca_ex+EX_R10(r13);
+	std	r11,\paca_ex+EX_R11(r13);
+	ld	r10,_NIP(r1)
+	ld	r11,_MSR(r1)
+	ld	r0,GPR0(r1)
+	ld	r1,GPR1(r1)
+	mtspr	\srr0,r10
+	mtspr	\srr1,r11
+	ld	r10,\paca_ex+EX_R10(r13)
+	ld	r11,\paca_ex+EX_R11(r13)
+	mfspr	r13,\scratch
+.endm
+
+ret_from_crit_except:
+	ret_from_level SPRN_CSRR0 SPRN_CSRR1 PACA_EXCRIT SPRN_SPRG_CRIT_SCRATCH
+	rfci
+
+ret_from_mc_except:
+	ret_from_level SPRN_MCSRR0 SPRN_MCSRR1 PACA_EXMC SPRN_SPRG_MC_SCRATCH
+	rfmci
 
 /* Exception prolog code for all exceptions */
 #define EXCEPTION_PROLOG(n, intnum, type, addition)	    		    \
@@ -81,22 +311,19 @@
 
 #define CRIT_SET_KSTACK						            \
 	ld	r1,PACA_CRIT_STACK(r13);				    \
-	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE;				    \
-	EXC_LEVEL_EXCEPTION_PROLOG(CRIT);
+	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE
 #define SPRN_CRIT_SRR0	SPRN_CSRR0
 #define SPRN_CRIT_SRR1	SPRN_CSRR1
 
 #define DBG_SET_KSTACK						            \
 	ld	r1,PACA_DBG_STACK(r13);					    \
-	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE;				    \
-	EXC_LEVEL_EXCEPTION_PROLOG(DBG);
+	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE
 #define SPRN_DBG_SRR0	SPRN_DSRR0
 #define SPRN_DBG_SRR1	SPRN_DSRR1
 
 #define MC_SET_KSTACK						            \
 	ld	r1,PACA_MC_STACK(r13);					    \
-	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE;				    \
-	EXC_LEVEL_EXCEPTION_PROLOG(MC);
+	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE
 #define SPRN_MC_SRR0	SPRN_MCSRR0
 #define SPRN_MC_SRR1	SPRN_MCSRR1
 
@@ -322,27 +549,25 @@ interrupt_end_book3e:
 	START_EXCEPTION(critical_input);
 	CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON_CRIT(0x100)
-//	INTS_DISABLE
-//	bl	special_reg_save_crit
-//	CHECK_NAPPING();
-//	addi	r3,r1,STACK_FRAME_OVERHEAD
-//	bl	.critical_exception
-//	b	ret_from_crit_except
-	b	.
+	EXCEPTION_COMMON_CRIT(0x100)
+	bl	.save_nvgprs
+	bl	special_reg_save
+	CHECK_NAPPING();
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unknown_exception
+	b	ret_from_crit_except
 
 /* Machine Check Interrupt */
 	START_EXCEPTION(machine_check);
 	MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK,
 			    PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON_MC(0x000)
-//	INTS_DISABLE
-//	bl	special_reg_save_mc
-//	addi	r3,r1,STACK_FRAME_OVERHEAD
-//	CHECK_NAPPING();
-//	bl	.machine_check_exception
-//	b	ret_from_mc_except
-	b	.
+	EXCEPTION_COMMON_MC(0x000)
+	bl	.save_nvgprs
+	bl	special_reg_save
+	CHECK_NAPPING();
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.machine_check_exception
+	b	ret_from_mc_except
 
 /* Data Storage Interrupt */
 	START_EXCEPTION(data_storage)
@@ -461,14 +686,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	START_EXCEPTION(watchdog);
 	CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON_CRIT(0x9f0)
-//	INTS_DISABLE
-//	bl	special_reg_save_crit
-//	CHECK_NAPPING();
-//	addi	r3,r1,STACK_FRAME_OVERHEAD
-//	bl	.unknown_exception
-//	b	ret_from_crit_except
-	b	.
+	EXCEPTION_COMMON_CRIT(0x9f0)
+	bl	.save_nvgprs
+	bl	special_reg_save
+	CHECK_NAPPING();
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_BOOKE_WDT
+	bl	.WatchdogException
+#else
+	bl	.unknown_exception
+#endif
+	b	ret_from_crit_except
 
 /* System Call Interrupt */
 	START_EXCEPTION(system_call)
@@ -541,7 +769,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	 */
 	mfspr	r14,SPRN_DBSR
 	EXCEPTION_COMMON_CRIT(0xd00)
-	INTS_DISABLE
 	std	r14,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	mr	r4,r14
@@ -634,14 +861,13 @@ kernel_dbg_exc:
 	START_EXCEPTION(doorbell_crit);
 	CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON_CRIT(0x2a0)
-//	INTS_DISABLE
-//	bl	special_reg_save_crit
-//	CHECK_NAPPING();
-//	addi	r3,r1,STACK_FRAME_OVERHEAD
-//	bl	.doorbell_critical_exception
-//	b	ret_from_crit_except
-	b	.
+	EXCEPTION_COMMON_CRIT(0x2a0)
+	bl	.save_nvgprs
+	bl	special_reg_save
+	CHECK_NAPPING();
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unknown_exception
+	b	ret_from_crit_except
 
 /*
  *	Guest doorbell interrupt
@@ -661,14 +887,13 @@ kernel_dbg_exc:
 	START_EXCEPTION(guest_doorbell_crit);
 	CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
 			      PROLOG_ADDITION_NONE)
-//	EXCEPTION_COMMON_CRIT(0x2e0)
-//	INTS_DISABLE
-//	bl	special_reg_save_crit
-//	CHECK_NAPPING();
-//	addi	r3,r1,STACK_FRAME_OVERHEAD
-//	bl	.guest_doorbell_critical_exception
-//	b	ret_from_crit_except
-	b	.
+	EXCEPTION_COMMON_CRIT(0x2e0)
+	bl	.save_nvgprs
+	bl	special_reg_save
+	CHECK_NAPPING();
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unknown_exception
+	b	ret_from_crit_except
 
 /* Hypervisor call */
 	START_EXCEPTION(hypercall);
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index b37a58e..ae3d5b7 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -144,6 +144,15 @@ int mmu_vmemmap_psize;		/* Page size used for the virtual mem map */
 int book3e_htw_mode;		/* HW tablewalk?  Value is PPC_HTW_* */
 unsigned long linear_map_top;	/* Top of linear mapping */
 
+
+/*
+ * Number of bytes to add to SPRN_SPRG_TLB_EXFRAME on crit/mcheck/debug
+ * exceptions.  This is used for bolted and e6500 TLB miss handlers which
+ * do not modify this SPRG in the TLB miss code; for other TLB miss handlers,
+ * this is set to zero.
+ */
+int extlb_level_exc;
+
 #endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_PPC_FSL_BOOK3E
@@ -559,6 +568,7 @@ static void setup_mmu_htw(void)
 		break;
 #ifdef CONFIG_PPC_FSL_BOOK3E
 	case PPC_HTW_E6500:
+		extlb_level_exc = EX_TLB_SIZE;
 		patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e);
 		patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e);
 		break;
@@ -652,6 +662,7 @@ static void __early_init_mmu(int boot_cpu)
 		memblock_enforce_memory_limit(linear_map_top);
 
 		if (book3e_htw_mode == PPC_HTW_NONE) {
+			extlb_level_exc = EX_TLB_SIZE;
 			patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
 			patch_exception(0x1e0,
 				exc_instruction_tlb_miss_bolted_book3e);
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 10/10] Revert "powerpc/watchdog: Don't enable interrupt on PPC64 BookE"
From: Scott Wood @ 2014-03-14  0:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Tiejun Chen, Wim Van Sebroeck, Laurentiu Tudor, Scott Wood,
	linuxppc-dev
In-Reply-To: <1394755249-8856-1-git-send-email-scottwood@freescale.com>

This reverts commit 3978bdb4ed653342b0be66c031bf61b72cc55d60, now that
critical interrupts are properly supported on ppc64 booke.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Cc: Laurentiu Tudor <Laurentiu.Tudor@freescale.com>
Cc: Wim Van Sebroeck <wim@iguana.be>
---
 drivers/watchdog/booke_wdt.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index f1b8d55..a8dbceb3 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -138,14 +138,6 @@ static void __booke_wdt_enable(void *data)
 	val &= ~WDTP_MASK;
 	val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
 
-#ifdef CONFIG_PPC_BOOK3E_64
-	/*
-	 * Crit ints are currently broken on PPC64 Book-E, so
-	 * just disable them for now.
-	 */
-	val &= ~TCR_WIE;
-#endif
-
 	mtspr(SPRN_TCR, val);
 }
 
-- 
1.8.3.2

^ permalink raw reply related

* Re: how do I increase default kernel stack size for my MPC8548 board?
From: Scott Wood @ 2014-03-14  0:11 UTC (permalink / raw)
  To: perth1415; +Cc: linuxppc-dev
In-Reply-To: <1394547564081-80712.post@n7.nabble.com>

On Tue, 2014-03-11 at 07:19 -0700, perth1415 wrote:
> Looks like I found the issue :-) The stack size for init task needs to be
> updated too. Right now it's by default set to 8K for PPC32.
> 
> In arch/powerpc/kernel/vmlinux.lds.S -
> ===
>     /* The initial task and kernel stack */
> #ifdef CONFIG_PPC32
>     . = ALIGN(8192);
> #else
>     . = ALIGN(16384);
> #endif
> ===
> 
> Problem is, how do we link this to THREAD_SHIFT?

Have you tried:

	. = ALIGN(THREAD_SIZE)

?

Or just use a newer kernel, where this is already done. :-)

-Scott

^ permalink raw reply

* powerpc/perf: patches for 3.15
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual

Hi folks,

This is the series of patches I have in my git tree to send to Ben.

https://github.com/mpe/powerpc-merge

These have all been to the list previously as-is, except for some of Cody's
which I've modified slightly to avoid depending on other peoples' trees.

The patch to fs/sysfs/group.c has already been merged by Greg, but we want to
carry it too so the code works prior to merging with his tree.

cheers

 Documentation/ABI/testing/sysfs-bus-event_source-devices-events  | 517 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7 |  23 ++++
 Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci |  43 +++++++
 arch/powerpc/include/asm/cputable.h                              |   6 +-
 arch/powerpc/include/asm/hvcall.h                                |   5 +
 arch/powerpc/include/asm/perf_event_server.h                     |   1 +
 arch/powerpc/include/asm/reg.h                                   |   3 +
 arch/powerpc/kernel/cputable.c                                   |   2 +-
 arch/powerpc/perf/Makefile                                       |   2 +
 arch/powerpc/perf/core-book3s.c                                  | 172 ++++++++++++++++++++++++--
 arch/powerpc/perf/hv-24x7-catalog.h                              |  33 +++++
 arch/powerpc/perf/hv-24x7.c                                      | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/powerpc/perf/hv-24x7.h                                      | 109 +++++++++++++++++
 arch/powerpc/perf/hv-common.c                                    |  39 ++++++
 arch/powerpc/perf/hv-common.h                                    |  36 ++++++
 arch/powerpc/perf/hv-gpci.c                                      | 294 ++++++++++++++++++++++++++++++++++++++++++++
 arch/powerpc/perf/hv-gpci.h                                      |  73 +++++++++++
 arch/powerpc/perf/power7-events-list.h                           |  10 ++
 arch/powerpc/perf/power8-pmu.c                                   |  78 +++++++++---
 arch/powerpc/platforms/pseries/Kconfig                           |  12 ++
 fs/sysfs/group.c                                                 |   7 +-
 21 files changed, 1941 insertions(+), 34 deletions(-)

^ permalink raw reply

* [PATCH 01/20] powerpc/perf: Make some new raw event codes available in sysfs
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Anshuman Khandual <khandual@linux.vnet.ibm.com>

This patchset adds some missing event list for POWER7 PMU raw
events which are exported through sysfs interface. Also updates
the ABI documentation to add all the sysfs exported raw events.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 .../testing/sysfs-bus-event_source-devices-events  | 517 +++++++++++++++++++++
 arch/powerpc/perf/power7-events-list.h             |  10 +
 2 files changed, 527 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
index 3c1cc24..7b40a3c 100644
--- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
@@ -57,6 +57,523 @@ What: 		/sys/devices/cpu/events/PM_1PLUS_PPC_CMPL
 		/sys/devices/cpu/events/PM_LD_REF_L1
 		/sys/devices/cpu/events/PM_RUN_CYC
 		/sys/devices/cpu/events/PM_RUN_INST_CMPL
+		/sys/devices/cpu/events/PM_IC_DEMAND_L2_BR_ALL
+		/sys/devices/cpu/events/PM_GCT_UTIL_7_TO_10_SLOTS
+		/sys/devices/cpu/events/PM_PMC2_SAVED
+		/sys/devices/cpu/events/PM_VSU0_16FLOP
+		/sys/devices/cpu/events/PM_MRK_LSU_DERAT_MISS
+		/sys/devices/cpu/events/PM_MRK_ST_CMPL
+		/sys/devices/cpu/events/PM_NEST_PAIR3_ADD
+		/sys/devices/cpu/events/PM_L2_ST_DISP
+		/sys/devices/cpu/events/PM_L2_CASTOUT_MOD
+		/sys/devices/cpu/events/PM_ISEG
+		/sys/devices/cpu/events/PM_MRK_INST_TIMEO
+		/sys/devices/cpu/events/PM_L2_RCST_DISP_FAIL_ADDR
+		/sys/devices/cpu/events/PM_LSU1_DC_PREF_STREAM_CONFIRM
+		/sys/devices/cpu/events/PM_IERAT_WR_64K
+		/sys/devices/cpu/events/PM_MRK_DTLB_MISS_16M
+		/sys/devices/cpu/events/PM_IERAT_MISS
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_LMEM
+		/sys/devices/cpu/events/PM_FLOP
+		/sys/devices/cpu/events/PM_THRD_PRIO_4_5_CYC
+		/sys/devices/cpu/events/PM_BR_PRED_TA
+		/sys/devices/cpu/events/PM_EXT_INT
+		/sys/devices/cpu/events/PM_VSU_FSQRT_FDIV
+		/sys/devices/cpu/events/PM_MRK_LD_MISS_EXPOSED_CYC
+		/sys/devices/cpu/events/PM_LSU1_LDF
+		/sys/devices/cpu/events/PM_IC_WRITE_ALL
+		/sys/devices/cpu/events/PM_LSU0_SRQ_STFWD
+		/sys/devices/cpu/events/PM_PTEG_FROM_RL2L3_MOD
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_DATA_FROM_L21_MOD
+		/sys/devices/cpu/events/PM_VSU1_SCAL_DOUBLE_ISSUED
+		/sys/devices/cpu/events/PM_VSU0_8FLOP
+		/sys/devices/cpu/events/PM_POWER_EVENT1
+		/sys/devices/cpu/events/PM_DISP_CLB_HELD_BAL
+		/sys/devices/cpu/events/PM_VSU1_2FLOP
+		/sys/devices/cpu/events/PM_LWSYNC_HELD
+		/sys/devices/cpu/events/PM_PTEG_FROM_DL2L3_SHR
+		/sys/devices/cpu/events/PM_INST_FROM_L21_MOD
+		/sys/devices/cpu/events/PM_IERAT_XLATE_WR_16MPLUS
+		/sys/devices/cpu/events/PM_IC_REQ_ALL
+		/sys/devices/cpu/events/PM_DSLB_MISS
+		/sys/devices/cpu/events/PM_L3_MISS
+		/sys/devices/cpu/events/PM_LSU0_L1_PREF
+		/sys/devices/cpu/events/PM_VSU_SCALAR_SINGLE_ISSUED
+		/sys/devices/cpu/events/PM_LSU1_DC_PREF_STREAM_CONFIRM_STRIDE
+		/sys/devices/cpu/events/PM_L2_INST
+		/sys/devices/cpu/events/PM_VSU0_FRSP
+		/sys/devices/cpu/events/PM_FLUSH_DISP
+		/sys/devices/cpu/events/PM_PTEG_FROM_L2MISS
+		/sys/devices/cpu/events/PM_VSU1_DQ_ISSUED
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_DMEM
+		/sys/devices/cpu/events/PM_LSU_FLUSH_ULD
+		/sys/devices/cpu/events/PM_PTEG_FROM_LMEM
+		/sys/devices/cpu/events/PM_MRK_DERAT_MISS_16M
+		/sys/devices/cpu/events/PM_THRD_ALL_RUN_CYC
+		/sys/devices/cpu/events/PM_MEM0_PREFETCH_DISP
+		/sys/devices/cpu/events/PM_MRK_STALL_CMPLU_CYC_COUNT
+		/sys/devices/cpu/events/PM_DATA_FROM_DL2L3_MOD
+		/sys/devices/cpu/events/PM_VSU_FRSP
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_MOD
+		/sys/devices/cpu/events/PM_PMC1_OVERFLOW
+		/sys/devices/cpu/events/PM_VSU0_SINGLE
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L3MISS
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_VSU0_VECTOR_SP_ISSUED
+		/sys/devices/cpu/events/PM_VSU1_FEST
+		/sys/devices/cpu/events/PM_MRK_INST_DISP
+		/sys/devices/cpu/events/PM_VSU0_COMPLEX_ISSUED
+		/sys/devices/cpu/events/PM_LSU1_FLUSH_UST
+		/sys/devices/cpu/events/PM_FXU_IDLE
+		/sys/devices/cpu/events/PM_LSU0_FLUSH_ULD
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_MOD
+		/sys/devices/cpu/events/PM_LSU_LMQ_SRQ_EMPTY_ALL_CYC
+		/sys/devices/cpu/events/PM_LSU1_REJECT_LMQ_FULL
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L21_MOD
+		/sys/devices/cpu/events/PM_INST_FROM_RL2L3_MOD
+		/sys/devices/cpu/events/PM_SHL_CREATED
+		/sys/devices/cpu/events/PM_L2_ST_HIT
+		/sys/devices/cpu/events/PM_DATA_FROM_DMEM
+		/sys/devices/cpu/events/PM_L3_LD_MISS
+		/sys/devices/cpu/events/PM_FXU1_BUSY_FXU0_IDLE
+		/sys/devices/cpu/events/PM_DISP_CLB_HELD_RES
+		/sys/devices/cpu/events/PM_L2_SN_SX_I_DONE
+		/sys/devices/cpu/events/PM_STCX_CMPL
+		/sys/devices/cpu/events/PM_VSU0_2FLOP
+		/sys/devices/cpu/events/PM_L3_PREF_MISS
+		/sys/devices/cpu/events/PM_LSU_SRQ_SYNC_CYC
+		/sys/devices/cpu/events/PM_LSU_REJECT_ERAT_MISS
+		/sys/devices/cpu/events/PM_L1_ICACHE_MISS
+		/sys/devices/cpu/events/PM_LSU1_FLUSH_SRQ
+		/sys/devices/cpu/events/PM_LD_REF_L1_LSU0
+		/sys/devices/cpu/events/PM_VSU0_FEST
+		/sys/devices/cpu/events/PM_VSU_VECTOR_SINGLE_ISSUED
+		/sys/devices/cpu/events/PM_FREQ_UP
+		/sys/devices/cpu/events/PM_DATA_FROM_LMEM
+		/sys/devices/cpu/events/PM_LSU1_LDX
+		/sys/devices/cpu/events/PM_PMC3_OVERFLOW
+		/sys/devices/cpu/events/PM_MRK_BR_MPRED
+		/sys/devices/cpu/events/PM_SHL_MATCH
+		/sys/devices/cpu/events/PM_MRK_BR_TAKEN
+		/sys/devices/cpu/events/PM_ISLB_MISS
+		/sys/devices/cpu/events/PM_DISP_HELD_THERMAL
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_RL2L3_SHR
+		/sys/devices/cpu/events/PM_LSU1_SRQ_STFWD
+		/sys/devices/cpu/events/PM_PTEG_FROM_DMEM
+		/sys/devices/cpu/events/PM_VSU_2FLOP
+		/sys/devices/cpu/events/PM_GCT_FULL_CYC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L3_CYC
+		/sys/devices/cpu/events/PM_LSU_SRQ_S0_ALLOC
+		/sys/devices/cpu/events/PM_MRK_DERAT_MISS_4K
+		/sys/devices/cpu/events/PM_BR_MPRED_TA
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L2MISS
+		/sys/devices/cpu/events/PM_DPU_HELD_POWER
+		/sys/devices/cpu/events/PM_MRK_VSU_FIN
+		/sys/devices/cpu/events/PM_LSU_SRQ_S0_VALID
+		/sys/devices/cpu/events/PM_GCT_EMPTY_CYC
+		/sys/devices/cpu/events/PM_IOPS_DISP
+		/sys/devices/cpu/events/PM_RUN_SPURR
+		/sys/devices/cpu/events/PM_PTEG_FROM_L21_MOD
+		/sys/devices/cpu/events/PM_VSU0_1FLOP
+		/sys/devices/cpu/events/PM_SNOOP_TLBIE
+		/sys/devices/cpu/events/PM_DATA_FROM_L3MISS
+		/sys/devices/cpu/events/PM_VSU_SINGLE
+		/sys/devices/cpu/events/PM_DTLB_MISS_16G
+		/sys/devices/cpu/events/PM_FLUSH
+		/sys/devices/cpu/events/PM_L2_LD_HIT
+		/sys/devices/cpu/events/PM_NEST_PAIR2_AND
+		/sys/devices/cpu/events/PM_VSU1_1FLOP
+		/sys/devices/cpu/events/PM_IC_PREF_REQ
+		/sys/devices/cpu/events/PM_L3_LD_HIT
+		/sys/devices/cpu/events/PM_DISP_HELD
+		/sys/devices/cpu/events/PM_L2_LD
+		/sys/devices/cpu/events/PM_LSU_FLUSH_SRQ
+		/sys/devices/cpu/events/PM_BC_PLUS_8_CONV
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_MOD_CYC
+		/sys/devices/cpu/events/PM_L2_RCST_BUSY_RC_FULL
+		/sys/devices/cpu/events/PM_TB_BIT_TRANS
+		/sys/devices/cpu/events/PM_THERMAL_MAX
+		/sys/devices/cpu/events/PM_LSU1_FLUSH_ULD
+		/sys/devices/cpu/events/PM_LSU1_REJECT_LHS
+		/sys/devices/cpu/events/PM_LSU_LRQ_S0_ALLOC
+		/sys/devices/cpu/events/PM_L3_CO_L31
+		/sys/devices/cpu/events/PM_POWER_EVENT4
+		/sys/devices/cpu/events/PM_DATA_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_BR_UNCOND
+		/sys/devices/cpu/events/PM_LSU1_DC_PREF_STREAM_ALLOC
+		/sys/devices/cpu/events/PM_PMC4_REWIND
+		/sys/devices/cpu/events/PM_L2_RCLD_DISP
+		/sys/devices/cpu/events/PM_THRD_PRIO_2_3_CYC
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L2MISS
+		/sys/devices/cpu/events/PM_IC_DEMAND_L2_BHT_REDIRECT
+		/sys/devices/cpu/events/PM_DATA_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_IC_PREF_CANCEL_L2
+		/sys/devices/cpu/events/PM_MRK_FIN_STALL_CYC_COUNT
+		/sys/devices/cpu/events/PM_BR_PRED_CCACHE
+		/sys/devices/cpu/events/PM_GCT_UTIL_1_TO_2_SLOTS
+		/sys/devices/cpu/events/PM_MRK_ST_CMPL_INT
+		/sys/devices/cpu/events/PM_LSU_TWO_TABLEWALK_CYC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L3MISS
+		/sys/devices/cpu/events/PM_LSU_SET_MPRED
+		/sys/devices/cpu/events/PM_FLUSH_DISP_TLBIE
+		/sys/devices/cpu/events/PM_VSU1_FCONV
+		/sys/devices/cpu/events/PM_DERAT_MISS_16G
+		/sys/devices/cpu/events/PM_INST_FROM_LMEM
+		/sys/devices/cpu/events/PM_IC_DEMAND_L2_BR_REDIRECT
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L2
+		/sys/devices/cpu/events/PM_PTEG_FROM_L2
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_SHR_CYC
+		/sys/devices/cpu/events/PM_MRK_DTLB_MISS_4K
+		/sys/devices/cpu/events/PM_VSU0_FPSCR
+		/sys/devices/cpu/events/PM_VSU1_VECT_DOUBLE_ISSUED
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_RL2L3_MOD
+		/sys/devices/cpu/events/PM_MEM0_RQ_DISP
+		/sys/devices/cpu/events/PM_L2_LD_MISS
+		/sys/devices/cpu/events/PM_VMX_RESULT_SAT_1
+		/sys/devices/cpu/events/PM_L1_PREF
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_LMEM_CYC
+		/sys/devices/cpu/events/PM_GRP_IC_MISS_NONSPEC
+		/sys/devices/cpu/events/PM_PB_NODE_PUMP
+		/sys/devices/cpu/events/PM_SHL_MERGED
+		/sys/devices/cpu/events/PM_NEST_PAIR1_ADD
+		/sys/devices/cpu/events/PM_DATA_FROM_L3
+		/sys/devices/cpu/events/PM_LSU_FLUSH
+		/sys/devices/cpu/events/PM_LSU_SRQ_SYNC_COUNT
+		/sys/devices/cpu/events/PM_PMC2_OVERFLOW
+		/sys/devices/cpu/events/PM_LSU_LDF
+		/sys/devices/cpu/events/PM_POWER_EVENT3
+		/sys/devices/cpu/events/PM_DISP_WT
+		/sys/devices/cpu/events/PM_IC_BANK_CONFLICT
+		/sys/devices/cpu/events/PM_BR_MPRED_CR_TA
+		/sys/devices/cpu/events/PM_L2_INST_MISS
+		/sys/devices/cpu/events/PM_NEST_PAIR2_ADD
+		/sys/devices/cpu/events/PM_MRK_LSU_FLUSH
+		/sys/devices/cpu/events/PM_L2_LDST
+		/sys/devices/cpu/events/PM_INST_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_VSU0_FIN
+		/sys/devices/cpu/events/PM_VSU1_FCONV
+		/sys/devices/cpu/events/PM_INST_FROM_RMEM
+		/sys/devices/cpu/events/PM_DISP_CLB_HELD_TLBIE
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_DMEM_CYC
+		/sys/devices/cpu/events/PM_BR_PRED_CR
+		/sys/devices/cpu/events/PM_LSU_REJECT
+		/sys/devices/cpu/events/PM_GCT_UTIL_3_TO_6_SLOTS
+		/sys/devices/cpu/events/PM_CMPLU_STALL_END_GCT_NOSLOT
+		/sys/devices/cpu/events/PM_LSU0_REJECT_LMQ_FULL
+		/sys/devices/cpu/events/PM_VSU_FEST
+		/sys/devices/cpu/events/PM_NEST_PAIR0_AND
+		/sys/devices/cpu/events/PM_PTEG_FROM_L3
+		/sys/devices/cpu/events/PM_POWER_EVENT2
+		/sys/devices/cpu/events/PM_IC_PREF_CANCEL_PAGE
+		/sys/devices/cpu/events/PM_VSU0_FSQRT_FDIV
+		/sys/devices/cpu/events/PM_MRK_GRP_CMPL
+		/sys/devices/cpu/events/PM_VSU0_SCAL_DOUBLE_ISSUED
+		/sys/devices/cpu/events/PM_GRP_DISP
+		/sys/devices/cpu/events/PM_LSU0_LDX
+		/sys/devices/cpu/events/PM_DATA_FROM_L2
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_MOD
+		/sys/devices/cpu/events/PM_VSU0_VECT_DOUBLE_ISSUED
+		/sys/devices/cpu/events/PM_VSU1_2FLOP_DOUBLE
+		/sys/devices/cpu/events/PM_THRD_PRIO_6_7_CYC
+		/sys/devices/cpu/events/PM_BC_PLUS_8_RSLV_TAKEN
+		/sys/devices/cpu/events/PM_BR_MPRED_CR
+		/sys/devices/cpu/events/PM_L3_CO_MEM
+		/sys/devices/cpu/events/PM_DATA_FROM_RL2L3_MOD
+		/sys/devices/cpu/events/PM_LSU_SRQ_FULL_CYC
+		/sys/devices/cpu/events/PM_TABLEWALK_CYC
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_RMEM
+		/sys/devices/cpu/events/PM_LSU_SRQ_STFWD
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_RMEM
+		/sys/devices/cpu/events/PM_FXU0_FIN
+		/sys/devices/cpu/events/PM_LSU1_L1_SW_PREF
+		/sys/devices/cpu/events/PM_PTEG_FROM_L31_MOD
+		/sys/devices/cpu/events/PM_PMC5_OVERFLOW
+		/sys/devices/cpu/events/PM_LD_REF_L1_LSU1
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L21_SHR
+		/sys/devices/cpu/events/PM_DATA_FROM_RMEM
+		/sys/devices/cpu/events/PM_VSU0_SCAL_SINGLE_ISSUED
+		/sys/devices/cpu/events/PM_BR_MPRED_LSTACK
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_MOD_CYC
+		/sys/devices/cpu/events/PM_LSU0_FLUSH_UST
+		/sys/devices/cpu/events/PM_LSU_NCST
+		/sys/devices/cpu/events/PM_BR_TAKEN
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_LMEM
+		/sys/devices/cpu/events/PM_DTLB_MISS_4K
+		/sys/devices/cpu/events/PM_PMC4_SAVED
+		/sys/devices/cpu/events/PM_VSU1_PERMUTE_ISSUED
+		/sys/devices/cpu/events/PM_SLB_MISS
+		/sys/devices/cpu/events/PM_LSU1_FLUSH_LRQ
+		/sys/devices/cpu/events/PM_DTLB_MISS
+		/sys/devices/cpu/events/PM_VSU1_FRSP
+		/sys/devices/cpu/events/PM_VSU_VECTOR_DOUBLE_ISSUED
+		/sys/devices/cpu/events/PM_L2_CASTOUT_SHR
+		/sys/devices/cpu/events/PM_DATA_FROM_DL2L3_SHR
+		/sys/devices/cpu/events/PM_VSU1_STF
+		/sys/devices/cpu/events/PM_ST_FIN
+		/sys/devices/cpu/events/PM_PTEG_FROM_L21_SHR
+		/sys/devices/cpu/events/PM_L2_LOC_GUESS_WRONG
+		/sys/devices/cpu/events/PM_MRK_STCX_FAIL
+		/sys/devices/cpu/events/PM_LSU0_REJECT_LHS
+		/sys/devices/cpu/events/PM_IC_PREF_CANCEL_HIT
+		/sys/devices/cpu/events/PM_L3_PREF_BUSY
+		/sys/devices/cpu/events/PM_MRK_BRU_FIN
+		/sys/devices/cpu/events/PM_LSU1_NCLD
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L31_MOD
+		/sys/devices/cpu/events/PM_LSU_NCLD
+		/sys/devices/cpu/events/PM_LSU_LDX
+		/sys/devices/cpu/events/PM_L2_LOC_GUESS_CORRECT
+		/sys/devices/cpu/events/PM_THRESH_TIMEO
+		/sys/devices/cpu/events/PM_L3_PREF_ST
+		/sys/devices/cpu/events/PM_DISP_CLB_HELD_SYNC
+		/sys/devices/cpu/events/PM_VSU_SIMPLE_ISSUED
+		/sys/devices/cpu/events/PM_VSU1_SINGLE
+		/sys/devices/cpu/events/PM_DATA_TABLEWALK_CYC
+		/sys/devices/cpu/events/PM_L2_RC_ST_DONE
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L21_MOD
+		/sys/devices/cpu/events/PM_LARX_LSU1
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_RMEM
+		/sys/devices/cpu/events/PM_DISP_CLB_HELD
+		/sys/devices/cpu/events/PM_DERAT_MISS_4K
+		/sys/devices/cpu/events/PM_L2_RCLD_DISP_FAIL_ADDR
+		/sys/devices/cpu/events/PM_SEG_EXCEPTION
+		/sys/devices/cpu/events/PM_FLUSH_DISP_SB
+		/sys/devices/cpu/events/PM_L2_DC_INV
+		/sys/devices/cpu/events/PM_PTEG_FROM_DL2L3_MOD
+		/sys/devices/cpu/events/PM_DSEG
+		/sys/devices/cpu/events/PM_BR_PRED_LSTACK
+		/sys/devices/cpu/events/PM_VSU0_STF
+		/sys/devices/cpu/events/PM_LSU_FX_FIN
+		/sys/devices/cpu/events/PM_DERAT_MISS_16M
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_DL2L3_MOD
+		/sys/devices/cpu/events/PM_GCT_UTIL_11_PLUS_SLOTS
+		/sys/devices/cpu/events/PM_INST_FROM_L3
+		/sys/devices/cpu/events/PM_MRK_IFU_FIN
+		/sys/devices/cpu/events/PM_ITLB_MISS
+		/sys/devices/cpu/events/PM_VSU_STF
+		/sys/devices/cpu/events/PM_LSU_FLUSH_UST
+		/sys/devices/cpu/events/PM_L2_LDST_MISS
+		/sys/devices/cpu/events/PM_FXU1_FIN
+		/sys/devices/cpu/events/PM_SHL_DEALLOCATED
+		/sys/devices/cpu/events/PM_L2_SN_M_WR_DONE
+		/sys/devices/cpu/events/PM_LSU_REJECT_SET_MPRED
+		/sys/devices/cpu/events/PM_L3_PREF_LD
+		/sys/devices/cpu/events/PM_L2_SN_M_RD_DONE
+		/sys/devices/cpu/events/PM_MRK_DERAT_MISS_16G
+		/sys/devices/cpu/events/PM_VSU_FCONV
+		/sys/devices/cpu/events/PM_ANY_THRD_RUN_CYC
+		/sys/devices/cpu/events/PM_LSU_LMQ_FULL_CYC
+		/sys/devices/cpu/events/PM_MRK_LSU_REJECT_LHS
+		/sys/devices/cpu/events/PM_MRK_LD_MISS_L1_CYC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L2_CYC
+		/sys/devices/cpu/events/PM_INST_IMC_MATCH_DISP
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_RMEM_CYC
+		/sys/devices/cpu/events/PM_VSU0_SIMPLE_ISSUED
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_RL2L3_SHR
+		/sys/devices/cpu/events/PM_VSU_FMA_DOUBLE
+		/sys/devices/cpu/events/PM_VSU_4FLOP
+		/sys/devices/cpu/events/PM_VSU1_FIN
+		/sys/devices/cpu/events/PM_NEST_PAIR1_AND
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_RL2L3_MOD
+		/sys/devices/cpu/events/PM_PTEG_FROM_RMEM
+		/sys/devices/cpu/events/PM_LSU_LRQ_S0_VALID
+		/sys/devices/cpu/events/PM_LSU0_LDF
+		/sys/devices/cpu/events/PM_FLUSH_COMPLETION
+		/sys/devices/cpu/events/PM_ST_MISS_L1
+		/sys/devices/cpu/events/PM_L2_NODE_PUMP
+		/sys/devices/cpu/events/PM_INST_FROM_DL2L3_SHR
+		/sys/devices/cpu/events/PM_MRK_STALL_CMPLU_CYC
+		/sys/devices/cpu/events/PM_VSU1_DENORM
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_SHR_CYC
+		/sys/devices/cpu/events/PM_NEST_PAIR0_ADD
+		/sys/devices/cpu/events/PM_INST_FROM_L3MISS
+		/sys/devices/cpu/events/PM_EE_OFF_EXT_INT
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_DMEM
+		/sys/devices/cpu/events/PM_INST_FROM_DL2L3_MOD
+		/sys/devices/cpu/events/PM_PMC6_OVERFLOW
+		/sys/devices/cpu/events/PM_VSU_2FLOP_DOUBLE
+		/sys/devices/cpu/events/PM_TLB_MISS
+		/sys/devices/cpu/events/PM_FXU_BUSY
+		/sys/devices/cpu/events/PM_L2_RCLD_DISP_FAIL_OTHER
+		/sys/devices/cpu/events/PM_LSU_REJECT_LMQ_FULL
+		/sys/devices/cpu/events/PM_IC_RELOAD_SHR
+		/sys/devices/cpu/events/PM_GRP_MRK
+		/sys/devices/cpu/events/PM_MRK_ST_NEST
+		/sys/devices/cpu/events/PM_VSU1_FSQRT_FDIV
+		/sys/devices/cpu/events/PM_LSU0_FLUSH_LRQ
+		/sys/devices/cpu/events/PM_LARX_LSU0
+		/sys/devices/cpu/events/PM_IBUF_FULL_CYC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_SHR_CYC
+		/sys/devices/cpu/events/PM_LSU_DC_PREF_STREAM_ALLOC
+		/sys/devices/cpu/events/PM_GRP_MRK_CYC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_SHR_CYC
+		/sys/devices/cpu/events/PM_L2_GLOB_GUESS_CORRECT
+		/sys/devices/cpu/events/PM_LSU_REJECT_LHS
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_LMEM
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L3
+		/sys/devices/cpu/events/PM_FREQ_DOWN
+		/sys/devices/cpu/events/PM_PB_RETRY_NODE_PUMP
+		/sys/devices/cpu/events/PM_INST_FROM_RL2L3_SHR
+		/sys/devices/cpu/events/PM_MRK_INST_ISSUED
+		/sys/devices/cpu/events/PM_PTEG_FROM_L3MISS
+		/sys/devices/cpu/events/PM_RUN_PURR
+		/sys/devices/cpu/events/PM_MRK_GRP_IC_MISS
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L3
+		/sys/devices/cpu/events/PM_PTEG_FROM_RL2L3_SHR
+		/sys/devices/cpu/events/PM_LSU_FLUSH_LRQ
+		/sys/devices/cpu/events/PM_MRK_DERAT_MISS_64K
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_DL2L3_MOD
+		/sys/devices/cpu/events/PM_L2_ST_MISS
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L21_SHR
+		/sys/devices/cpu/events/PM_LWSYNC
+		/sys/devices/cpu/events/PM_LSU0_DC_PREF_STREAM_CONFIRM_STRIDE
+		/sys/devices/cpu/events/PM_MRK_LSU_FLUSH_LRQ
+		/sys/devices/cpu/events/PM_INST_IMC_MATCH_CMPL
+		/sys/devices/cpu/events/PM_NEST_PAIR3_AND
+		/sys/devices/cpu/events/PM_PB_RETRY_SYS_PUMP
+		/sys/devices/cpu/events/PM_MRK_INST_FIN
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_DL2L3_SHR
+		/sys/devices/cpu/events/PM_INST_FROM_L31_MOD
+		/sys/devices/cpu/events/PM_MRK_DTLB_MISS_64K
+		/sys/devices/cpu/events/PM_LSU_FIN
+		/sys/devices/cpu/events/PM_MRK_LSU_REJECT
+		/sys/devices/cpu/events/PM_L2_CO_FAIL_BUSY
+		/sys/devices/cpu/events/PM_MEM0_WQ_DISP
+		/sys/devices/cpu/events/PM_DATA_FROM_L31_MOD
+		/sys/devices/cpu/events/PM_THERMAL_WARN
+		/sys/devices/cpu/events/PM_VSU0_4FLOP
+		/sys/devices/cpu/events/PM_BR_MPRED_CCACHE
+		/sys/devices/cpu/events/PM_L1_DEMAND_WRITE
+		/sys/devices/cpu/events/PM_FLUSH_BR_MPRED
+		/sys/devices/cpu/events/PM_MRK_DTLB_MISS_16G
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_DMEM
+		/sys/devices/cpu/events/PM_L2_RCST_DISP
+		/sys/devices/cpu/events/PM_LSU_PARTIAL_CDF
+		/sys/devices/cpu/events/PM_DISP_CLB_HELD_SB
+		/sys/devices/cpu/events/PM_VSU0_FMA_DOUBLE
+		/sys/devices/cpu/events/PM_FXU0_BUSY_FXU1_IDLE
+		/sys/devices/cpu/events/PM_IC_DEMAND_CYC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_SHR
+		/sys/devices/cpu/events/PM_MRK_LSU_FLUSH_UST
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L3MISS
+		/sys/devices/cpu/events/PM_VSU_DENORM
+		/sys/devices/cpu/events/PM_MRK_LSU_PARTIAL_CDF
+		/sys/devices/cpu/events/PM_INST_FROM_L21_SHR
+		/sys/devices/cpu/events/PM_IC_PREF_WRITE
+		/sys/devices/cpu/events/PM_BR_PRED
+		/sys/devices/cpu/events/PM_INST_FROM_DMEM
+		/sys/devices/cpu/events/PM_IC_PREF_CANCEL_ALL
+		/sys/devices/cpu/events/PM_LSU_DC_PREF_STREAM_CONFIRM
+		/sys/devices/cpu/events/PM_MRK_LSU_FLUSH_SRQ
+		/sys/devices/cpu/events/PM_MRK_FIN_STALL_CYC
+		/sys/devices/cpu/events/PM_L2_RCST_DISP_FAIL_OTHER
+		/sys/devices/cpu/events/PM_VSU1_DD_ISSUED
+		/sys/devices/cpu/events/PM_PTEG_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_DATA_FROM_L21_SHR
+		/sys/devices/cpu/events/PM_LSU0_NCLD
+		/sys/devices/cpu/events/PM_VSU1_4FLOP
+		/sys/devices/cpu/events/PM_VSU1_8FLOP
+		/sys/devices/cpu/events/PM_VSU_8FLOP
+		/sys/devices/cpu/events/PM_LSU_LMQ_SRQ_EMPTY_CYC
+		/sys/devices/cpu/events/PM_DTLB_MISS_64K
+		/sys/devices/cpu/events/PM_THRD_CONC_RUN_INST
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L2
+		/sys/devices/cpu/events/PM_PB_SYS_PUMP
+		/sys/devices/cpu/events/PM_VSU_FIN
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_MOD
+		/sys/devices/cpu/events/PM_THRD_PRIO_0_1_CYC
+		/sys/devices/cpu/events/PM_DERAT_MISS_64K
+		/sys/devices/cpu/events/PM_PMC2_REWIND
+		/sys/devices/cpu/events/PM_INST_FROM_L2
+		/sys/devices/cpu/events/PM_GRP_BR_MPRED_NONSPEC
+		/sys/devices/cpu/events/PM_INST_DISP
+		/sys/devices/cpu/events/PM_MEM0_RD_CANCEL_TOTAL
+		/sys/devices/cpu/events/PM_LSU0_DC_PREF_STREAM_CONFIRM
+		/sys/devices/cpu/events/PM_L1_DCACHE_RELOAD_VALID
+		/sys/devices/cpu/events/PM_VSU_SCALAR_DOUBLE_ISSUED
+		/sys/devices/cpu/events/PM_L3_PREF_HIT
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L31_MOD
+		/sys/devices/cpu/events/PM_MRK_FXU_FIN
+		/sys/devices/cpu/events/PM_PMC4_OVERFLOW
+		/sys/devices/cpu/events/PM_MRK_PTEG_FROM_L3
+		/sys/devices/cpu/events/PM_LSU0_LMQ_LHR_MERGE
+		/sys/devices/cpu/events/PM_BTAC_HIT
+		/sys/devices/cpu/events/PM_L3_RD_BUSY
+		/sys/devices/cpu/events/PM_LSU0_L1_SW_PREF
+		/sys/devices/cpu/events/PM_INST_FROM_L2MISS
+		/sys/devices/cpu/events/PM_LSU0_DC_PREF_STREAM_ALLOC
+		/sys/devices/cpu/events/PM_L2_ST
+		/sys/devices/cpu/events/PM_VSU0_DENORM
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_SHR
+		/sys/devices/cpu/events/PM_BR_PRED_CR_TA
+		/sys/devices/cpu/events/PM_VSU0_FCONV
+		/sys/devices/cpu/events/PM_MRK_LSU_FLUSH_ULD
+		/sys/devices/cpu/events/PM_BTAC_MISS
+		/sys/devices/cpu/events/PM_MRK_LD_MISS_EXPOSED_CYC_COUNT
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L2
+		/sys/devices/cpu/events/PM_LSU_DCACHE_RELOAD_VALID
+		/sys/devices/cpu/events/PM_VSU_FMA
+		/sys/devices/cpu/events/PM_LSU0_FLUSH_SRQ
+		/sys/devices/cpu/events/PM_LSU1_L1_PREF
+		/sys/devices/cpu/events/PM_IOPS_CMPL
+		/sys/devices/cpu/events/PM_L2_SYS_PUMP
+		/sys/devices/cpu/events/PM_L2_RCLD_BUSY_RC_FULL
+		/sys/devices/cpu/events/PM_LSU_LMQ_S0_ALLOC
+		/sys/devices/cpu/events/PM_FLUSH_DISP_SYNC
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_MOD_CYC
+		/sys/devices/cpu/events/PM_L2_IC_INV
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_MOD_CYC
+		/sys/devices/cpu/events/PM_L3_PREF_LDST
+		/sys/devices/cpu/events/PM_LSU_SRQ_EMPTY_CYC
+		/sys/devices/cpu/events/PM_LSU_LMQ_S0_VALID
+		/sys/devices/cpu/events/PM_FLUSH_PARTIAL
+		/sys/devices/cpu/events/PM_VSU1_FMA_DOUBLE
+		/sys/devices/cpu/events/PM_1PLUS_PPC_DISP
+		/sys/devices/cpu/events/PM_DATA_FROM_L2MISS
+		/sys/devices/cpu/events/PM_SUSPENDED
+		/sys/devices/cpu/events/PM_VSU0_FMA
+		/sys/devices/cpu/events/PM_STCX_FAIL
+		/sys/devices/cpu/events/PM_VSU0_FSQRT_FDIV_DOUBLE
+		/sys/devices/cpu/events/PM_DC_PREF_DST
+		/sys/devices/cpu/events/PM_VSU1_SCAL_SINGLE_ISSUED
+		/sys/devices/cpu/events/PM_L3_HIT
+		/sys/devices/cpu/events/PM_L2_GLOB_GUESS_WRONG
+		/sys/devices/cpu/events/PM_MRK_DFU_FIN
+		/sys/devices/cpu/events/PM_INST_FROM_L1
+		/sys/devices/cpu/events/PM_IC_DEMAND_REQ
+		/sys/devices/cpu/events/PM_VSU1_FSQRT_FDIV_DOUBLE
+		/sys/devices/cpu/events/PM_VSU1_FMA
+		/sys/devices/cpu/events/PM_MRK_LD_MISS_L1
+		/sys/devices/cpu/events/PM_VSU0_2FLOP_DOUBLE
+		/sys/devices/cpu/events/PM_LSU_DC_PREF_STRIDED_STREAM_CONFIRM
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_L31_SHR
+		/sys/devices/cpu/events/PM_MRK_LSU_REJECT_ERAT_MISS
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_L2MISS
+		/sys/devices/cpu/events/PM_DATA_FROM_RL2L3_SHR
+		/sys/devices/cpu/events/PM_INST_FROM_PREF
+		/sys/devices/cpu/events/PM_VSU1_SQ
+		/sys/devices/cpu/events/PM_L2_LD_DISP
+		/sys/devices/cpu/events/PM_L2_DISP_ALL
+		/sys/devices/cpu/events/PM_THRD_GRP_CMPL_BOTH_CYC
+		/sys/devices/cpu/events/PM_VSU_FSQRT_FDIV_DOUBLE
+		/sys/devices/cpu/events/PM_INST_PTEG_FROM_DL2L3_SHR
+		/sys/devices/cpu/events/PM_VSU_1FLOP
+		/sys/devices/cpu/events/PM_HV_CYC
+		/sys/devices/cpu/events/PM_MRK_LSU_FIN
+		/sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_SHR
+		/sys/devices/cpu/events/PM_DTLB_MISS_16M
+		/sys/devices/cpu/events/PM_LSU1_LMQ_LHR_MERGE
+		/sys/devices/cpu/events/PM_IFU_FIN
+		/sys/devices/cpu/events/PM_1THRD_CON_RUN_INSTR
+		/sys/devices/cpu/events/PM_CMPLU_STALL_COUNT
+		/sys/devices/cpu/events/PM_MEM0_PB_RD_CL
+		/sys/devices/cpu/events/PM_THRD_1_RUN_CYC
+		/sys/devices/cpu/events/PM_THRD_2_CONC_RUN_INSTR
+		/sys/devices/cpu/events/PM_THRD_2_RUN_CYC
+		/sys/devices/cpu/events/PM_THRD_3_CONC_RUN_INST
+		/sys/devices/cpu/events/PM_THRD_3_RUN_CYC
+		/sys/devices/cpu/events/PM_THRD_4_CONC_RUN_INST
+		/sys/devices/cpu/events/PM_THRD_4_RUN_CYC
 
 Date:		2013/01/08
 
diff --git a/arch/powerpc/perf/power7-events-list.h b/arch/powerpc/perf/power7-events-list.h
index 687790a..64f13d9 100644
--- a/arch/powerpc/perf/power7-events-list.h
+++ b/arch/powerpc/perf/power7-events-list.h
@@ -546,3 +546,13 @@ EVENT(PM_MRK_DATA_FROM_RL2L3_SHR,             0x1d04c)
 EVENT(PM_DTLB_MISS_16M,                       0x4c05e)
 EVENT(PM_LSU1_LMQ_LHR_MERGE,                  0x0d09a)
 EVENT(PM_IFU_FIN,                             0x40066)
+EVENT(PM_1THRD_CON_RUN_INSTR,                 0x30062)
+EVENT(PM_CMPLU_STALL_COUNT,                   0x4000B)
+EVENT(PM_MEM0_PB_RD_CL,                       0x30083)
+EVENT(PM_THRD_1_RUN_CYC,                      0x10060)
+EVENT(PM_THRD_2_CONC_RUN_INSTR,               0x40062)
+EVENT(PM_THRD_2_RUN_CYC,                      0x20060)
+EVENT(PM_THRD_3_CONC_RUN_INST,                0x10062)
+EVENT(PM_THRD_3_RUN_CYC,                      0x30060)
+EVENT(PM_THRD_4_CONC_RUN_INST,                0x20062)
+EVENT(PM_THRD_4_RUN_CYC,                      0x40060)
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 02/20] powerpc/perf: Define perf_event_print_debug() to print PMU register values
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Anshuman Khandual <khandual@linux.vnet.ibm.com>

Currently the sysrq ShowRegs command does not print any PMU registers as
we have an empty definition for perf_event_print_debug(). This patch
defines perf_event_print_debug() to print various PMU registers.

Example output:

CPU: 0 PMU registers, ppmu = POWER7 n_counters = 6
PMC1:  00000000 PMC2: 00000000 PMC3: 00000000 PMC4: 00000000
PMC5:  00000000 PMC6: 00000000 PMC7: deadbeef PMC8: deadbeef
MMCR0: 0000000080000000 MMCR1: 0000000000000000 MMCRA: 0f00000001000000
SIAR:  0000000000000000 SDAR:  0000000000000000 SIER:  0000000000000000

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
[mpe: Fix 32 bit build and rework formatting for compactness]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/perf_event_server.h |  1 +
 arch/powerpc/perf/core-book3s.c              | 55 ++++++++++++++++++++++++++--
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 3fd2f1b..9ed73714 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <uapi/asm/perf_event.h>
 
+/* Update perf_event_print_debug() if this changes */
 #define MAX_HWEVENTS		8
 #define MAX_EVENT_ALTERNATIVES	8
 #define MAX_LIMITED_HWCOUNTERS	2
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 67cf220..704d1c5 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -563,10 +563,6 @@ out:
 
 static void perf_event_interrupt(struct pt_regs *regs);
 
-void perf_event_print_debug(void)
-{
-}
-
 /*
  * Read one performance monitor counter (PMC).
  */
@@ -645,6 +641,57 @@ static void write_pmc(int idx, unsigned long val)
 	}
 }
 
+/* Called from sysrq_handle_showregs() */
+void perf_event_print_debug(void)
+{
+	unsigned long sdar, sier, flags;
+	u32 pmcs[MAX_HWEVENTS];
+	int i;
+
+	if (!ppmu->n_counter)
+		return;
+
+	local_irq_save(flags);
+
+	pr_info("CPU: %d PMU registers, ppmu = %s n_counters = %d",
+		 smp_processor_id(), ppmu->name, ppmu->n_counter);
+
+	for (i = 0; i < ppmu->n_counter; i++)
+		pmcs[i] = read_pmc(i + 1);
+
+	for (; i < MAX_HWEVENTS; i++)
+		pmcs[i] = 0xdeadbeef;
+
+	pr_info("PMC1:  %08x PMC2: %08x PMC3: %08x PMC4: %08x\n",
+		 pmcs[0], pmcs[1], pmcs[2], pmcs[3]);
+
+	if (ppmu->n_counter > 4)
+		pr_info("PMC5:  %08x PMC6: %08x PMC7: %08x PMC8: %08x\n",
+			 pmcs[4], pmcs[5], pmcs[6], pmcs[7]);
+
+	pr_info("MMCR0: %016lx MMCR1: %016lx MMCRA: %016lx\n",
+		mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCRA));
+
+	sdar = sier = 0;
+#ifdef CONFIG_PPC64
+	sdar = mfspr(SPRN_SDAR);
+
+	if (ppmu->flags & PPMU_HAS_SIER)
+		sier = mfspr(SPRN_SIER);
+
+	if (ppmu->flags & PPMU_EBB) {
+		pr_info("MMCR2: %016lx EBBHR: %016lx\n",
+			mfspr(SPRN_MMCR2), mfspr(SPRN_EBBHR));
+		pr_info("EBBRR: %016lx BESCR: %016lx\n",
+			mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
+	}
+#endif
+	pr_info("SIAR:  %016lx SDAR:  %016lx SIER:  %016lx\n",
+		mfspr(SPRN_SIAR), sdar, sier);
+
+	local_irq_restore(flags);
+}
+
 /*
  * Check if a set of events can all go on the PMU at once.
  * If they can't, this will look at alternative codes for the events
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 03/20] powerpc: Add a cpu feature CPU_FTR_PMAO_BUG
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

Some power8 revisions have a hardware bug where we can lose a
Performance Monitor (PMU) exception under certain circumstances.

We will be adding a workaround for this case, see the next commit for
details. The observed behaviour is that writing PMAO doesn't cause an
exception as we would expect, hence the name of the feature.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/cputable.h | 6 ++++--
 arch/powerpc/kernel/cputable.c      | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 617cc76..bc23477 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -189,6 +189,7 @@ extern const char *powerpc_base_platform;
 #define	CPU_FTR_HAS_PPR			LONG_ASM_CONST(0x0200000000000000)
 #define CPU_FTR_DAWR			LONG_ASM_CONST(0x0400000000000000)
 #define CPU_FTR_DABRX			LONG_ASM_CONST(0x0800000000000000)
+#define CPU_FTR_PMAO_BUG		LONG_ASM_CONST(0x1000000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -445,6 +446,7 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
 	    CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
 	    CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP)
+#define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -466,8 +468,8 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_POSSIBLE	\
 	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
 	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 |	\
-	    CPU_FTRS_POWER7 | CPU_FTRS_POWER8 | CPU_FTRS_CELL |		\
-	    CPU_FTRS_PA6T | CPU_FTR_VSX)
+	    CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 |	\
+	    CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX)
 #endif
 #else
 enum {
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 6c8dd5d..c1faade 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -510,7 +510,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x004b0000,
 		.cpu_name		= "POWER8E (raw)",
-		.cpu_features		= CPU_FTRS_POWER8,
+		.cpu_features		= CPU_FTRS_POWER8E,
 		.cpu_user_features	= COMMON_USER_POWER8,
 		.cpu_user_features2	= COMMON_USER2_POWER8,
 		.mmu_features		= MMU_FTRS_POWER8,
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 04/20] powerpc/perf: Add lost exception workaround
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

Some power8 revisions have a hardware bug where we can lose a PMU
exception, this commit adds a workaround to detect the bad condition and
rectify the situation.

See the comment in the commit for a full description.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/reg.h  |   2 +
 arch/powerpc/perf/core-book3s.c | 100 +++++++++++++++++++++++++++++++++++++++-
 arch/powerpc/perf/power8-pmu.c  |   5 ++
 3 files changed, 105 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 90c06ec..3003472 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -670,6 +670,7 @@
 #define   MMCR0_PMC1CE	0x00008000UL /* PMC1 count enable*/
 #define   MMCR0_PMCjCE	0x00004000UL /* PMCj count enable*/
 #define   MMCR0_TRIGGER	0x00002000UL /* TRIGGER enable */
+#define   MMCR0_PMAO_SYNC 0x00000800UL /* PMU interrupt is synchronous */
 #define   MMCR0_PMAO	0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */
 #define   MMCR0_SHRFC	0x00000040UL /* SHRre freeze conditions between threads */
 #define   MMCR0_FC56	0x00000010UL /* freeze counters 5 and 6 */
@@ -703,6 +704,7 @@
 #define SPRN_EBBHR	804	/* Event based branch handler register */
 #define SPRN_EBBRR	805	/* Event based branch return register */
 #define SPRN_BESCR	806	/* Branch event status and control register */
+#define   BESCR_GE	0x8000000000000000ULL /* Global Enable */
 #define SPRN_WORT	895	/* Workload optimization register - thread */
 
 #define SPRN_PMC1	787
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 704d1c5..53ac1b2 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -120,6 +120,7 @@ static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
 static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
 void power_pmu_flush_branch_stack(void) {}
 static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
+static void pmao_restore_workaround(bool ebb) { }
 #endif /* CONFIG_PPC32 */
 
 static bool regs_use_siar(struct pt_regs *regs)
@@ -545,10 +546,18 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
 	/* Enable EBB and read/write to all 6 PMCs for userspace */
 	mmcr0 |= MMCR0_EBE | MMCR0_PMCC_U6;
 
-	/* Add any bits from the user reg, FC or PMAO */
+	/*
+	 * Add any bits from the user MMCR0, FC or PMAO. This is compatible
+	 * with pmao_restore_workaround() because we may add PMAO but we never
+	 * clear it here.
+	 */
 	mmcr0 |= current->thread.mmcr0;
 
-	/* Be careful not to set PMXE if userspace had it cleared */
+	/*
+	 * Be careful not to set PMXE if userspace had it cleared. This is also
+	 * compatible with pmao_restore_workaround() because it has already
+	 * cleared PMXE and we leave PMAO alone.
+	 */
 	if (!(current->thread.mmcr0 & MMCR0_PMXE))
 		mmcr0 &= ~MMCR0_PMXE;
 
@@ -559,6 +568,91 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
 out:
 	return mmcr0;
 }
+
+static void pmao_restore_workaround(bool ebb)
+{
+	unsigned pmcs[6];
+
+	if (!cpu_has_feature(CPU_FTR_PMAO_BUG))
+		return;
+
+	/*
+	 * On POWER8E there is a hardware defect which affects the PMU context
+	 * switch logic, ie. power_pmu_disable/enable().
+	 *
+	 * When a counter overflows PMXE is cleared and FC/PMAO is set in MMCR0
+	 * by the hardware. Sometime later the actual PMU exception is
+	 * delivered.
+	 *
+	 * If we context switch, or simply disable/enable, the PMU prior to the
+	 * exception arriving, the exception will be lost when we clear PMAO.
+	 *
+	 * When we reenable the PMU, we will write the saved MMCR0 with PMAO
+	 * set, and this _should_ generate an exception. However because of the
+	 * defect no exception is generated when we write PMAO, and we get
+	 * stuck with no counters counting but no exception delivered.
+	 *
+	 * The workaround is to detect this case and tweak the hardware to
+	 * create another pending PMU exception.
+	 *
+	 * We do that by setting up PMC6 (cycles) for an imminent overflow and
+	 * enabling the PMU. That causes a new exception to be generated in the
+	 * chip, but we don't take it yet because we have interrupts hard
+	 * disabled. We then write back the PMU state as we want it to be seen
+	 * by the exception handler. When we reenable interrupts the exception
+	 * handler will be called and see the correct state.
+	 *
+	 * The logic is the same for EBB, except that the exception is gated by
+	 * us having interrupts hard disabled as well as the fact that we are
+	 * not in userspace. The exception is finally delivered when we return
+	 * to userspace.
+	 */
+
+	/* Only if PMAO is set and PMAO_SYNC is clear */
+	if ((current->thread.mmcr0 & (MMCR0_PMAO | MMCR0_PMAO_SYNC)) != MMCR0_PMAO)
+		return;
+
+	/* If we're doing EBB, only if BESCR[GE] is set */
+	if (ebb && !(current->thread.bescr & BESCR_GE))
+		return;
+
+	/*
+	 * We are already soft-disabled in power_pmu_enable(). We need to hard
+	 * enable to actually prevent the PMU exception from firing.
+	 */
+	hard_irq_disable();
+
+	/*
+	 * This is a bit gross, but we know we're on POWER8E and have 6 PMCs.
+	 * Using read/write_pmc() in a for loop adds 12 function calls and
+	 * almost doubles our code size.
+	 */
+	pmcs[0] = mfspr(SPRN_PMC1);
+	pmcs[1] = mfspr(SPRN_PMC2);
+	pmcs[2] = mfspr(SPRN_PMC3);
+	pmcs[3] = mfspr(SPRN_PMC4);
+	pmcs[4] = mfspr(SPRN_PMC5);
+	pmcs[5] = mfspr(SPRN_PMC6);
+
+	/* Ensure all freeze bits are unset */
+	mtspr(SPRN_MMCR2, 0);
+
+	/* Set up PMC6 to overflow in one cycle */
+	mtspr(SPRN_PMC6, 0x7FFFFFFE);
+
+	/* Enable exceptions and unfreeze PMC6 */
+	mtspr(SPRN_MMCR0, MMCR0_PMXE | MMCR0_PMCjCE | MMCR0_PMAO);
+
+	/* Now we need to refreeze and restore the PMCs */
+	mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMAO);
+
+	mtspr(SPRN_PMC1, pmcs[0]);
+	mtspr(SPRN_PMC2, pmcs[1]);
+	mtspr(SPRN_PMC3, pmcs[2]);
+	mtspr(SPRN_PMC4, pmcs[3]);
+	mtspr(SPRN_PMC5, pmcs[4]);
+	mtspr(SPRN_PMC6, pmcs[5]);
+}
 #endif /* CONFIG_PPC64 */
 
 static void perf_event_interrupt(struct pt_regs *regs);
@@ -1191,6 +1285,8 @@ static void power_pmu_enable(struct pmu *pmu)
 	cpuhw->mmcr[0] |= MMCR0_PMXE | MMCR0_FCECE;
 
  out_enable:
+	pmao_restore_workaround(ebb);
+
 	mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]);
 
 	mb();
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 96cee20..64f04cf 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt)	"power8-pmu: " fmt
+
 #include <linux/kernel.h>
 #include <linux/perf_event.h>
 #include <asm/firmware.h>
@@ -774,6 +776,9 @@ static int __init init_power8_pmu(void)
 	/* Tell userspace that EBB is supported */
 	cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
 
+	if (cpu_has_feature(CPU_FTR_PMAO_BUG))
+		pr_info("PMAO restore workaround active.\n");
+
 	return 0;
 }
 early_initcall(init_power8_pmu);
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 05/20] powerpc/perf: Reject EBB events which specify a sample_type
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

Although we already block EBB events which request sampling using
sample_period, technically it's possible for an event to set sample_type
but not sample_period.

Nothing terrible will happen if an EBB event does specify sample_type,
but it signals a major confusion on the part of userspace, and so we do
them the favor of rejecting it.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/core-book3s.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 53ac1b2..1e095fd 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -503,8 +503,11 @@ static int ebb_event_check(struct perf_event *event)
 		if (!leader->attr.pinned || !leader->attr.exclusive)
 			return -EINVAL;
 
-		if (event->attr.inherit || event->attr.sample_period ||
-		    event->attr.enable_on_exec || event->attr.freq)
+		if (event->attr.freq ||
+		    event->attr.inherit ||
+		    event->attr.sample_type ||
+		    event->attr.sample_period ||
+		    event->attr.enable_on_exec)
 			return -EINVAL;
 	}
 
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 06/20] powerpc/perf: Clean up the EBB hash defines a little
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

Rather than using PERF_EVENT_CONFIG_EBB_SHIFT everywhere, add an
EVENT_EBB_SHIFT like every other event and use that.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/power8-pmu.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 64f04cf..1d7c442 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -119,6 +119,7 @@
  */
 
 #define EVENT_EBB_MASK		1ull
+#define EVENT_EBB_SHIFT		PERF_EVENT_CONFIG_EBB_SHIFT
 #define EVENT_THR_CMP_SHIFT	40	/* Threshold CMP value */
 #define EVENT_THR_CMP_MASK	0x3ff
 #define EVENT_THR_CTL_SHIFT	32	/* Threshold control value (start/stop) */
@@ -151,7 +152,7 @@
 	 (EVENT_UNIT_MASK      << EVENT_UNIT_SHIFT)		|	\
 	 (EVENT_COMBINE_MASK   << EVENT_COMBINE_SHIFT)		|	\
 	 (EVENT_MARKED_MASK    << EVENT_MARKED_SHIFT)		|	\
-	 (EVENT_EBB_MASK       << PERF_EVENT_CONFIG_EBB_SHIFT)	|	\
+	 (EVENT_EBB_MASK       << EVENT_EBB_SHIFT)		|	\
 	  EVENT_PSEL_MASK)
 
 /* MMCRA IFM bits - POWER8 */
@@ -267,10 +268,10 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 	pmc   = (event >> EVENT_PMC_SHIFT)        & EVENT_PMC_MASK;
 	unit  = (event >> EVENT_UNIT_SHIFT)       & EVENT_UNIT_MASK;
 	cache = (event >> EVENT_CACHE_SEL_SHIFT)  & EVENT_CACHE_SEL_MASK;
-	ebb   = (event >> PERF_EVENT_CONFIG_EBB_SHIFT) & EVENT_EBB_MASK;
+	ebb   = (event >> EVENT_EBB_SHIFT)        & EVENT_EBB_MASK;
 
 	/* Clear the EBB bit in the event, so event checks work below */
-	event &= ~(EVENT_EBB_MASK << PERF_EVENT_CONFIG_EBB_SHIFT);
+	event &= ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
 
 	if (pmc) {
 		if (pmc > 6)
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 07/20] powerpc/perf: Avoid mutating event in power8_get_constraint()
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

We only need to mask the EBB bit out of the event for the check of the
special PMC 5 & 6 events. So use a local to do it just for that code,
rather than changing the event value for the life of the function.

While we're there move the set of mask and value after all the checks.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/power8-pmu.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 1d7c442..67aab10 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -270,18 +270,20 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 	cache = (event >> EVENT_CACHE_SEL_SHIFT)  & EVENT_CACHE_SEL_MASK;
 	ebb   = (event >> EVENT_EBB_SHIFT)        & EVENT_EBB_MASK;
 
-	/* Clear the EBB bit in the event, so event checks work below */
-	event &= ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
-
 	if (pmc) {
+		u64 base_event;
+
 		if (pmc > 6)
 			return -1;
 
-		mask  |= CNST_PMC_MASK(pmc);
-		value |= CNST_PMC_VAL(pmc);
+		/* Ignore Linux defined bits when checking event below */
+		base_event = event & ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
 
-		if (pmc >= 5 && event != 0x500fa && event != 0x600f4)
+		if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
 			return -1;
+
+		mask  |= CNST_PMC_MASK(pmc);
+		value |= CNST_PMC_VAL(pmc);
 	}
 
 	if (pmc <= 4) {
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 08/20] powerpc/perf: Add BHRB constraint and IFM MMCRA handling for EBB
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

We want a way for users of EBB (Event Based Branches) to also access the
BHRB (Branch History Rolling Buffer). EBB does not interoperate with our
existing BHRB support, which is wired into the generic Linux branch
stack sampling support.

To support EBB & BHRB we add three new bits to the event code. The first
bit indicates that the event wants access to the BHRB, and the other two
bits indicate the desired IFM (Instruction Filtering Mode).

We allow multiple events to request access to the BHRB, but they must
agree on the IFM value. Events which are not interested in the BHRB can
also interoperate with events which do.

Finally we program the desired IFM value into MMCRA. Although we do this
for every event, we know that the value will be identical for all events
that request BHRB access.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/power8-pmu.c | 53 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 67aab10..3ad363d 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -64,9 +64,11 @@
  *
  *        60        56        52        48        44        40        36        32
  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
- *   |                                 [      thresh_cmp     ]   [  thresh_ctl   ]
- *   |                                                                   |
- *   *- EBB (Linux)                      thresh start/stop OR FAB match -*
+ *   | | [ ]                           [      thresh_cmp     ]   [  thresh_ctl   ]
+ *   | |  |                                                              |
+ *   | |  *- IFM (Linux)                 thresh start/stop OR FAB match -*
+ *   | *- BHRB (Linux)
+ *   *- EBB (Linux)
  *
  *        28        24        20        16        12         8         4         0
  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
@@ -116,10 +118,18 @@
  *	MMCRA[57:59] = sample[0:2]	(RAND_SAMP_ELIG)
  *	MMCRA[61:62] = sample[3:4]	(RAND_SAMP_MODE)
  *
+ * if EBB and BHRB:
+ *	MMCRA[32:33] = IFM
+ *
  */
 
 #define EVENT_EBB_MASK		1ull
 #define EVENT_EBB_SHIFT		PERF_EVENT_CONFIG_EBB_SHIFT
+#define EVENT_BHRB_MASK		1ull
+#define EVENT_BHRB_SHIFT	62
+#define EVENT_WANTS_BHRB	(EVENT_BHRB_MASK << EVENT_BHRB_SHIFT)
+#define EVENT_IFM_MASK		3ull
+#define EVENT_IFM_SHIFT		60
 #define EVENT_THR_CMP_SHIFT	40	/* Threshold CMP value */
 #define EVENT_THR_CMP_MASK	0x3ff
 #define EVENT_THR_CTL_SHIFT	32	/* Threshold control value (start/stop) */
@@ -144,6 +154,12 @@
 #define EVENT_IS_MARKED		(EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
 #define EVENT_PSEL_MASK		0xff	/* PMCxSEL value */
 
+/* Bits defined by Linux */
+#define EVENT_LINUX_MASK	\
+	((EVENT_EBB_MASK  << EVENT_EBB_SHIFT)			|	\
+	 (EVENT_BHRB_MASK << EVENT_BHRB_SHIFT)			|	\
+	 (EVENT_IFM_MASK  << EVENT_IFM_SHIFT))
+
 #define EVENT_VALID_MASK	\
 	((EVENT_THRESH_MASK    << EVENT_THRESH_SHIFT)		|	\
 	 (EVENT_SAMPLE_MASK    << EVENT_SAMPLE_SHIFT)		|	\
@@ -152,7 +168,7 @@
 	 (EVENT_UNIT_MASK      << EVENT_UNIT_SHIFT)		|	\
 	 (EVENT_COMBINE_MASK   << EVENT_COMBINE_SHIFT)		|	\
 	 (EVENT_MARKED_MASK    << EVENT_MARKED_SHIFT)		|	\
-	 (EVENT_EBB_MASK       << EVENT_EBB_SHIFT)		|	\
+	  EVENT_LINUX_MASK					|	\
 	  EVENT_PSEL_MASK)
 
 /* MMCRA IFM bits - POWER8 */
@@ -176,10 +192,11 @@
  *
  *        28        24        20        16        12         8         4         0
  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
- *                   |   [ ]   [  sample ]   [     ]   [6] [5]   [4] [3]   [2] [1]
- *              EBB -*    |                     |
- *                        |                     |      Count of events for each PMC.
- *      L1 I/D qualifier -*                     |        p1, p2, p3, p4, p5, p6.
+ *               [ ] |   [ ]   [  sample ]   [     ]   [6] [5]   [4] [3]   [2] [1]
+ *                |  |    |                     |
+ *      BHRB IFM -*  |    |                     |      Count of events for each PMC.
+ *              EBB -*    |                     |        p1, p2, p3, p4, p5, p6.
+ *      L1 I/D qualifier -*                     |
  *                     nc - number of counters -*
  *
  * The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints
@@ -198,6 +215,9 @@
 #define CNST_EBB_VAL(v)		(((v) & EVENT_EBB_MASK) << 24)
 #define CNST_EBB_MASK		CNST_EBB_VAL(EVENT_EBB_MASK)
 
+#define CNST_IFM_VAL(v)		(((v) & EVENT_IFM_MASK) << 25)
+#define CNST_IFM_MASK		CNST_IFM_VAL(EVENT_IFM_MASK)
+
 #define CNST_L1_QUAL_VAL(v)	(((v) & 3) << 22)
 #define CNST_L1_QUAL_MASK	CNST_L1_QUAL_VAL(3)
 
@@ -244,6 +264,7 @@
 #define MMCRA_THR_SEL_SHIFT		16
 #define MMCRA_THR_CMP_SHIFT		32
 #define MMCRA_SDAR_MODE_TLB		(1ull << 42)
+#define MMCRA_IFM_SHIFT			30
 
 
 static inline bool event_is_fab_match(u64 event)
@@ -277,7 +298,7 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 			return -1;
 
 		/* Ignore Linux defined bits when checking event below */
-		base_event = event & ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
+		base_event = event & ~EVENT_LINUX_MASK;
 
 		if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
 			return -1;
@@ -347,6 +368,15 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 		/* EBB events must specify the PMC */
 		return -1;
 
+	if (event & EVENT_WANTS_BHRB) {
+		if (!ebb)
+			/* Only EBB events can request BHRB */
+			return -1;
+
+		mask  |= CNST_IFM_MASK;
+		value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT);
+	}
+
 	/*
 	 * All events must agree on EBB, either all request it or none.
 	 * EBB events are pinned & exclusive, so this should never actually
@@ -436,6 +466,11 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
 			mmcra |= val << MMCRA_THR_CMP_SHIFT;
 		}
 
+		if (event[i] & EVENT_WANTS_BHRB) {
+			val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK;
+			mmcra |= val << MMCRA_IFM_SHIFT;
+		}
+
 		hwc[i] = pmc - 1;
 	}
 
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 09/20] powerpc/perf: Enable BHRB access for EBB events
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

The previous commit added constraint and register handling to allow
processes using EBB (Event Based Branches) to request access to the BHRB
(Branch History Rolling Buffer).

With that in place we can allow processes using EBB to access the BHRB.
This is achieved by setting BHRBA in MMCR0 when we enable EBB access. We
must also clear BHRBA when we are disabling.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/reg.h  |  1 +
 arch/powerpc/perf/core-book3s.c | 10 ++++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 3003472..980e8db 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -664,6 +664,7 @@
 #define   MMCR0_PMXE	0x04000000UL /* performance monitor exception enable */
 #define   MMCR0_FCECE	0x02000000UL /* freeze ctrs on enabled cond or event */
 #define   MMCR0_TBEE	0x00400000UL /* time base exception enable */
+#define   MMCR0_BHRBA	0x00200000UL /* BHRB Access allowed in userspace */
 #define   MMCR0_EBE	0x00100000UL /* Event based branch enable */
 #define   MMCR0_PMCC	0x000c0000UL /* PMC control */
 #define   MMCR0_PMCC_U6	0x00080000UL /* PMC1-6 are R/W by user (PR) */
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 1e095fd..4520c93 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -78,6 +78,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
 #define MMCR0_FC56		0
 #define MMCR0_PMAO		0
 #define MMCR0_EBE		0
+#define MMCR0_BHRBA		0
 #define MMCR0_PMCC		0
 #define MMCR0_PMCC_U6		0
 
@@ -546,8 +547,8 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
 	if (!ebb)
 		goto out;
 
-	/* Enable EBB and read/write to all 6 PMCs for userspace */
-	mmcr0 |= MMCR0_EBE | MMCR0_PMCC_U6;
+	/* Enable EBB and read/write to all 6 PMCs and BHRB for userspace */
+	mmcr0 |= MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC_U6;
 
 	/*
 	 * Add any bits from the user MMCR0, FC or PMAO. This is compatible
@@ -1117,11 +1118,12 @@ static void power_pmu_disable(struct pmu *pmu)
 		}
 
 		/*
-		 * Set the 'freeze counters' bit, clear EBE/PMCC/PMAO/FC56.
+		 * Set the 'freeze counters' bit, clear EBE/BHRBA/PMCC/PMAO/FC56
 		 */
 		val  = mmcr0 = mfspr(SPRN_MMCR0);
 		val |= MMCR0_FC;
-		val &= ~(MMCR0_EBE | MMCR0_PMCC | MMCR0_PMAO | MMCR0_FC56);
+		val &= ~(MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC | MMCR0_PMAO |
+			 MMCR0_FC56);
 
 		/*
 		 * The barrier is to make sure the mtspr has been
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 10/20] sysfs: create bin_attributes under the requested group
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

bin_attributes created/updated in create_files() (such as those listed
via (struct device).attribute_groups) were not placed under the
specified group, and instead appeared in the base kobj directory.

Fix this by making bin_attributes use creating code similar to normal
attributes.

A quick grep shows that no one is using bin_attrs in a named attribute
group yet, so we can do this without breaking anything in usespace.

Note that I do not add is_visible() support to
bin_attributes, though that could be done as well.

This is a copy of the patch already merged in Greg's tree.

Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/sysfs/group.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 6b57938..aa04068 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -70,8 +70,11 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
 	if (grp->bin_attrs) {
 		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
 			if (update)
-				sysfs_remove_bin_file(kobj, *bin_attr);
-			error = sysfs_create_bin_file(kobj, *bin_attr);
+				kernfs_remove_by_name(parent,
+						(*bin_attr)->attr.name);
+			error = sysfs_add_file_mode_ns(parent,
+					&(*bin_attr)->attr, true,
+					(*bin_attr)->attr.mode, NULL);
 			if (error)
 				break;
 		}
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 11/20] powerpc: Add hvcalls for 24x7 and gpci (Get Performance Counter Info)
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/hvcall.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index d8b600b..5dbbb29 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -274,6 +274,11 @@
 /* Platform specific hcalls, used by KVM */
 #define H_RTAS			0xf000
 
+/* "Platform specific hcalls", provided by PHYP */
+#define H_GET_24X7_CATALOG_PAGE	0xF078
+#define H_GET_24X7_DATA		0xF07C
+#define H_GET_PERF_COUNTER_INFO	0xF080
+
 #ifndef __ASSEMBLY__
 
 /**
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 12/20] powerpc/perf: Add hv_gpci interface header
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

"H_GetPerformanceCounterInfo" (refered to as hv_gpci or just gpci from
here on) is an interface to retrieve specific performance counters and
other data from the hypervisor. All outputs have a fixed format. This
header only describes the portions of the interface that we plan on
using in linux at this time.

Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/hv-gpci.h | 73 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 arch/powerpc/perf/hv-gpci.h

diff --git a/arch/powerpc/perf/hv-gpci.h b/arch/powerpc/perf/hv-gpci.h
new file mode 100644
index 0000000..b25f460
--- /dev/null
+++ b/arch/powerpc/perf/hv-gpci.h
@@ -0,0 +1,73 @@
+#ifndef LINUX_POWERPC_PERF_HV_GPCI_H_
+#define LINUX_POWERPC_PERF_HV_GPCI_H_
+
+#include <linux/types.h>
+
+/* From the document "H_GetPerformanceCounterInfo Interface" v1.07 */
+
+/* H_GET_PERF_COUNTER_INFO argument */
+struct hv_get_perf_counter_info_params {
+	__be32 counter_request; /* I */
+	__be32 starting_index;  /* IO */
+	__be16 secondary_index; /* IO */
+	__be16 returned_values; /* O */
+	__be32 detail_rc; /* O, only needed when called via *_norets() */
+
+	/*
+	 * O, size each of counter_value element in bytes, only set for version
+	 * >= 0x3
+	 */
+	__be16 cv_element_size;
+
+	/* I, 0 (zero) for versions < 0x3 */
+	__u8 counter_info_version_in;
+
+	/* O, 0 (zero) if version < 0x3. Must be set to 0 when making hcall */
+	__u8 counter_info_version_out;
+	__u8 reserved[0xC];
+	__u8 counter_value[];
+} __packed;
+
+/*
+ * counter info version => fw version/reference (spec version)
+ *
+ * 8 => power8 (1.07)
+ * [7 is skipped by spec 1.07]
+ * 6 => TLBIE (1.07)
+ * 5 => v7r7m0.phyp (1.05)
+ * [4 skipped]
+ * 3 => v7r6m0.phyp (?)
+ * [1,2 skipped]
+ * 0 => v7r{2,3,4}m0.phyp (?)
+ */
+#define COUNTER_INFO_VERSION_CURRENT 0x8
+
+/*
+ * These determine the counter_value[] layout and the meaning of starting_index
+ * and secondary_index.
+ *
+ * Unless otherwise noted, @secondary_index is unused and ignored.
+ */
+enum counter_info_requests {
+
+	/* GENERAL */
+
+	/* @starting_index: must be -1 (to refer to the current partition)
+	 */
+	CIR_SYSTEM_PERFORMANCE_CAPABILITIES = 0X40,
+};
+
+struct cv_system_performance_capabilities {
+	/* If != 0, allowed to collect data from other partitions */
+	__u8 perf_collect_privileged;
+
+	/* These following are only valid if counter_info_version >= 0x3 */
+#define CV_CM_GA       (1 << 7)
+#define CV_CM_EXPANDED (1 << 6)
+#define CV_CM_LAB      (1 << 5)
+	/* remaining bits are reserved */
+	__u8 capability_mask;
+	__u8 reserved[0xE];
+} __packed;
+
+#endif
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 13/20] powerpc/perf: Add 24x7 interface headers
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

24x7 (also called hv_24x7 or H_24X7) is an interface to obtain
performance counters from the hypervisor. These counters do not have a
fixed format/possition and are instead documented in a "24x7 Catalog",
which is provided by the hypervisor (that interface is also documented
paritialy in the included hv-24x7-catalog.h and fully in at
https://raw.githubusercontent.com/jmesmon/catalog-24x7/master/hv-24x7-catalog.h ).

The 24x7 data access is simply a copy operation into a 4 dimentional
array of 64bit counters (from hypervisor to kernel memory). There is no
interupt triggered on overflow, these are completely disjoint from the
typical power pmu.

This method of obtaining performance counters from the hypervisor is
intended to paritialy replace the gpci interface.

Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/hv-24x7-catalog.h |  33 +++++++++++
 arch/powerpc/perf/hv-24x7.h         | 109 ++++++++++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+)
 create mode 100644 arch/powerpc/perf/hv-24x7-catalog.h
 create mode 100644 arch/powerpc/perf/hv-24x7.h

diff --git a/arch/powerpc/perf/hv-24x7-catalog.h b/arch/powerpc/perf/hv-24x7-catalog.h
new file mode 100644
index 0000000..21b19dd
--- /dev/null
+++ b/arch/powerpc/perf/hv-24x7-catalog.h
@@ -0,0 +1,33 @@
+#ifndef LINUX_POWERPC_PERF_HV_24X7_CATALOG_H_
+#define LINUX_POWERPC_PERF_HV_24X7_CATALOG_H_
+
+#include <linux/types.h>
+
+/* From document "24x7 Event and Group Catalog Formats Proposal" v0.15 */
+
+struct hv_24x7_catalog_page_0 {
+#define HV_24X7_CATALOG_MAGIC 0x32347837 /* "24x7" in ASCII */
+	__be32 magic;
+	__be32 length; /* In 4096 byte pages */
+	__be64 version; /* XXX: arbitrary? what's the meaning/useage/purpose? */
+	__u8 build_time_stamp[16]; /* "YYYYMMDDHHMMSS\0\0" */
+	__u8 reserved2[32];
+	__be16 schema_data_offs; /* in 4096 byte pages */
+	__be16 schema_data_len;  /* in 4096 byte pages */
+	__be16 schema_entry_count;
+	__u8 reserved3[2];
+	__be16 event_data_offs;
+	__be16 event_data_len;
+	__be16 event_entry_count;
+	__u8 reserved4[2];
+	__be16 group_data_offs; /* in 4096 byte pages */
+	__be16 group_data_len;  /* in 4096 byte pages */
+	__be16 group_entry_count;
+	__u8 reserved5[2];
+	__be16 formula_data_offs; /* in 4096 byte pages */
+	__be16 formula_data_len;  /* in 4096 byte pages */
+	__be16 formula_entry_count;
+	__u8 reserved6[2];
+} __packed;
+
+#endif
diff --git a/arch/powerpc/perf/hv-24x7.h b/arch/powerpc/perf/hv-24x7.h
new file mode 100644
index 0000000..720ebce
--- /dev/null
+++ b/arch/powerpc/perf/hv-24x7.h
@@ -0,0 +1,109 @@
+#ifndef LINUX_POWERPC_PERF_HV_24X7_H_
+#define LINUX_POWERPC_PERF_HV_24X7_H_
+
+#include <linux/types.h>
+
+struct hv_24x7_request {
+	/* PHYSICAL domains require enabling via phyp/hmc. */
+#define HV_24X7_PERF_DOMAIN_PHYSICAL_CHIP 0x01
+#define HV_24X7_PERF_DOMAIN_PHYSICAL_CORE 0x02
+#define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_HOME_CORE   0x03
+#define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_HOME_CHIP   0x04
+#define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_HOME_NODE   0x05
+#define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_REMOTE_NODE 0x06
+	__u8 performance_domain;
+	__u8 reserved[0x1];
+
+	/* bytes to read starting at @data_offset. must be a multiple of 8 */
+	__be16 data_size;
+
+	/*
+	 * byte offset within the perf domain to read from. must be 8 byte
+	 * aligned
+	 */
+	__be32 data_offset;
+
+	/*
+	 * only valid for VIRTUAL_PROCESSOR domains, ignored for others.
+	 * -1 means "current partition only"
+	 *  Enabling via phyp/hmc required for non-"-1" values. 0 forbidden
+	 *  unless requestor is 0.
+	 */
+	__be16 starting_lpar_ix;
+
+	/*
+	 * Ignored when @starting_lpar_ix == -1
+	 * Ignored when @performance_domain is not VIRTUAL_PROCESSOR_*
+	 * -1 means "infinite" or all
+	 */
+	__be16 max_num_lpars;
+
+	/* chip, core, or virtual processor based on @performance_domain */
+	__be16 starting_ix;
+	__be16 max_ix;
+} __packed;
+
+struct hv_24x7_request_buffer {
+	/* 0 - ? */
+	/* 1 - ? */
+#define HV_24X7_IF_VERSION_CURRENT 0x01
+	__u8 interface_version;
+	__u8 num_requests;
+	__u8 reserved[0xE];
+	struct hv_24x7_request requests[];
+} __packed;
+
+struct hv_24x7_result_element {
+	__be16 lpar_ix;
+
+	/*
+	 * represents the core, chip, or virtual processor based on the
+	 * request's @performance_domain
+	 */
+	__be16 domain_ix;
+
+	/* -1 if @performance_domain does not refer to a virtual processor */
+	__be32 lpar_cfg_instance_id;
+
+	/* size = @result_element_data_size of cointaining result. */
+	__u8 element_data[];
+} __packed;
+
+struct hv_24x7_result {
+	__u8 result_ix;
+
+	/*
+	 * 0 = not all result elements fit into the buffer, additional requests
+	 *     required
+	 * 1 = all result elements were returned
+	 */
+	__u8 results_complete;
+	__be16 num_elements_returned;
+
+	/* This is a copy of @data_size from the coresponding hv_24x7_request */
+	__be16 result_element_data_size;
+	__u8 reserved[0x2];
+
+	/* WARNING: only valid for first result element due to variable sizes
+	 *          of result elements */
+	/* struct hv_24x7_result_element[@num_elements_returned] */
+	struct hv_24x7_result_element elements[];
+} __packed;
+
+struct hv_24x7_data_result_buffer {
+	/* See versioning for request buffer */
+	__u8 interface_version;
+
+	__u8 num_results;
+	__u8 reserved[0x1];
+	__u8 failing_request_ix;
+	__be32 detailed_rc;
+	__be64 cec_cfg_instance_id;
+	__be64 catalog_version_num;
+	__u8 reserved2[0x8];
+	/* WARNING: only valid for the first result due to variable sizes of
+	 *	    results */
+	struct hv_24x7_result results[]; /* [@num_results] */
+} __packed;
+
+#endif
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 14/20] powerpc/perf: Add a shared interface to get gpci version and capabilities
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

This exposes a simple way to grab the firmware provided
collect_priveliged, ga, expanded, and lab capability bits. All of these
bits come in from the same gpci request, so we've exposed all of them.

Only the collect_priveliged bit is really used by the hv-gpci/hv-24x7
code, the other bits are simply exposed in sysfs to inform the user.

Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/hv-common.c | 39 +++++++++++++++++++++++++++++++++++++++
 arch/powerpc/perf/hv-common.h | 17 +++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 arch/powerpc/perf/hv-common.c
 create mode 100644 arch/powerpc/perf/hv-common.h

diff --git a/arch/powerpc/perf/hv-common.c b/arch/powerpc/perf/hv-common.c
new file mode 100644
index 0000000..47e02b3
--- /dev/null
+++ b/arch/powerpc/perf/hv-common.c
@@ -0,0 +1,39 @@
+#include <asm/io.h>
+#include <asm/hvcall.h>
+
+#include "hv-gpci.h"
+#include "hv-common.h"
+
+unsigned long hv_perf_caps_get(struct hv_perf_caps *caps)
+{
+	unsigned long r;
+	struct p {
+		struct hv_get_perf_counter_info_params params;
+		struct cv_system_performance_capabilities caps;
+	} __packed __aligned(sizeof(uint64_t));
+
+	struct p arg = {
+		.params = {
+			.counter_request = cpu_to_be32(
+					CIR_SYSTEM_PERFORMANCE_CAPABILITIES),
+			.starting_index = cpu_to_be32(-1),
+			.counter_info_version_in = 0,
+		}
+	};
+
+	r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
+			       virt_to_phys(&arg), sizeof(arg));
+
+	if (r)
+		return r;
+
+	pr_devel("capability_mask: 0x%x\n", arg.caps.capability_mask);
+
+	caps->version = arg.params.counter_info_version_out;
+	caps->collect_privileged = !!arg.caps.perf_collect_privileged;
+	caps->ga = !!(arg.caps.capability_mask & CV_CM_GA);
+	caps->expanded = !!(arg.caps.capability_mask & CV_CM_EXPANDED);
+	caps->lab = !!(arg.caps.capability_mask & CV_CM_LAB);
+
+	return r;
+}
diff --git a/arch/powerpc/perf/hv-common.h b/arch/powerpc/perf/hv-common.h
new file mode 100644
index 0000000..7e615bd
--- /dev/null
+++ b/arch/powerpc/perf/hv-common.h
@@ -0,0 +1,17 @@
+#ifndef LINUX_POWERPC_PERF_HV_COMMON_H_
+#define LINUX_POWERPC_PERF_HV_COMMON_H_
+
+#include <linux/types.h>
+
+struct hv_perf_caps {
+	u16 version;
+	u16 collect_privileged:1,
+	    ga:1,
+	    expanded:1,
+	    lab:1,
+	    unused:12;
+};
+
+unsigned long hv_perf_caps_get(struct hv_perf_caps *caps);
+
+#endif
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 15/20] powerpc/perf: Add macros for defining event fields & formats
From: Michael Ellerman @ 2014-03-14  5:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cody, khandual
In-Reply-To: <1394773245-18328-1-git-send-email-mpe@ellerman.id.au>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

Add two macros which generate functions to extract the relevent bits
from event->attr.config{,1,2}.

EVENT_DEFINE_RANGE() defines an accessor for a range of bits in the
event, as well as a "max" function that gives the maximum value of the
field based on the bit width.

EVENT_DEFINE_RANGE_FORMAT() defines the accessor & max routine and also
a format attribute for use in the PMU's attr_groups.

Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
[mpe: move to powerpc, ugly but descriptive macro names]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/hv-common.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/powerpc/perf/hv-common.h b/arch/powerpc/perf/hv-common.h
index 7e615bd..5d79cec 100644
--- a/arch/powerpc/perf/hv-common.h
+++ b/arch/powerpc/perf/hv-common.h
@@ -1,6 +1,7 @@
 #ifndef LINUX_POWERPC_PERF_HV_COMMON_H_
 #define LINUX_POWERPC_PERF_HV_COMMON_H_
 
+#include <linux/perf_event.h>
 #include <linux/types.h>
 
 struct hv_perf_caps {
@@ -14,4 +15,22 @@ struct hv_perf_caps {
 
 unsigned long hv_perf_caps_get(struct hv_perf_caps *caps);
 
+
+#define EVENT_DEFINE_RANGE_FORMAT(name, attr_var, bit_start, bit_end)	\
+PMU_FORMAT_ATTR(name, #attr_var ":" #bit_start "-" #bit_end);		\
+EVENT_DEFINE_RANGE(name, attr_var, bit_start, bit_end)
+
+#define EVENT_DEFINE_RANGE(name, attr_var, bit_start, bit_end)	\
+static u64 event_get_##name##_max(void)					\
+{									\
+	BUILD_BUG_ON((bit_start > bit_end)				\
+		    || (bit_end >= (sizeof(1ull) * 8)));		\
+	return (((1ull << (bit_end - bit_start)) - 1) << 1) + 1;	\
+}									\
+static u64 event_get_##name(struct perf_event *event)			\
+{									\
+	return (event->attr.attr_var >> (bit_start)) &			\
+		event_get_##name##_max();				\
+}
+
 #endif
-- 
1.8.3.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox