From: Mikael Pettersson <mikpe@csd.uu.se>

Part 2/3 of perfctr control API changes:
- Switch per-counter control fields from struct-of-arrays
  to array-of-struct layout, placed at the end of the
  perfctr_cpu_control struct for flexibility.
- Drop ____cacheline_aligned from per-cpu cache object.
- In per-cpu cache object, make interrupts_masked flag
  share cache line with the cache id field.

Signed-off-by: Mikael Pettersson <mikpe@csd.uu.se>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/perfctr/x86.c      |   46 ++++++++++++++++++-------------------
 25-akpm/include/asm-i386/perfctr.h |   12 +++++----
 2 files changed, 30 insertions(+), 28 deletions(-)

diff -puN drivers/perfctr/x86.c~perfctr-x86-update-2 drivers/perfctr/x86.c
--- 25/drivers/perfctr/x86.c~perfctr-x86-update-2	2004-11-28 00:51:56.443663712 -0800
+++ 25-akpm/drivers/perfctr/x86.c	2004-11-28 00:51:56.451662496 -0800
@@ -1,4 +1,4 @@
-/* $Id: x86.c,v 1.146 2004/08/02 17:29:23 mikpe Exp $
+/* $Id: x86.c,v 1.151 2004/11/24 00:28:23 mikpe Exp $
  * x86/x86_64 performance-monitoring counters driver.
  *
  * Copyright (C) 1999-2004  Mikael Pettersson
@@ -27,6 +27,9 @@ struct per_cpu_cache {	/* roughly a subs
 		unsigned int p5_cesr;
 		unsigned int id;	/* cache owner id */
 	} k1;
+#ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT
+	unsigned int interrupts_masked;
+#endif
 	struct {
 		/* NOTE: these caches have physical indices, not virtual */
 		unsigned int evntsel[18];
@@ -34,10 +37,7 @@ struct per_cpu_cache {	/* roughly a subs
 		unsigned int pebs_enable;
 		unsigned int pebs_matrix_vert;
 	} control;
-#ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT
-	unsigned int interrupts_masked;
-#endif
-} ____cacheline_aligned;
+};
 static DEFINE_PER_CPU(struct per_cpu_cache, per_cpu_cache);
 #define __get_cpu_cache(cpu) (&per_cpu(per_cpu_cache, cpu))
 #define get_cpu_cache() (&__get_cpu_var(per_cpu_cache))
@@ -247,11 +247,11 @@ static int p5_like_check_control(struct 
 	cesr_half[0] = 0;
 	cesr_half[1] = 0;
 	for(i = 0; i < state->control.nractrs; ++i) {
-		pmc = state->control.pmc_map[i];
+		pmc = state->control.pmc[i].map;
 		state->pmc[i].map = pmc;
 		if (pmc > 1 || cesr_half[pmc] != 0)
 			return -EINVAL;
-		evntsel = state->control.evntsel[i];
+		evntsel = state->control.pmc[i].evntsel;
 		/* protect reserved bits */
 		if ((evntsel & reserved_bits) != 0)
 			return -EPERM;
@@ -413,12 +413,12 @@ static int p6_like_check_control(struct 
 
 	pmc_mask = 0;
 	for(i = 0; i < nrctrs; ++i) {
-		pmc = state->control.pmc_map[i];
+		pmc = state->control.pmc[i].map;
 		state->pmc[i].map = pmc;
 		if (pmc >= (is_k7 ? 4 : 2) || (pmc_mask & (1<<pmc)))
 			return -EINVAL;
 		pmc_mask |= (1<<pmc);
-		evntsel = state->control.evntsel[i];
+		evntsel = state->control.pmc[i].evntsel;
 		/* protect reserved bits */
 		if (evntsel & P6_EVNTSEL_RESERVED)
 			return -EPERM;
@@ -555,7 +555,7 @@ static void p6_like_write_control(const 
 		return;
 	nrctrs = perfctr_cstatus_nrctrs(state->cstatus);
 	for(i = 0; i < nrctrs; ++i) {
-		unsigned int evntsel = state->control.evntsel[i];
+		unsigned int evntsel = state->control.pmc[i].evntsel;
 		unsigned int pmc = state->pmc[i].map;
 		if (evntsel != cache->control.evntsel[pmc]) {
 			cache->control.evntsel[pmc] = evntsel;
@@ -639,12 +639,12 @@ static int vc3_check_control(struct perf
 	if (state->control.nrictrs || state->control.nractrs > 1)
 		return -EINVAL;
 	if (state->control.nractrs == 1) {
-		if (state->control.pmc_map[0] != 1)
+		if (state->control.pmc[0].map != 1)
 			return -EINVAL;
 		state->pmc[0].map = 1;
-		if (state->control.evntsel[0] & VC3_EVNTSEL1_RESERVED)
+		if (state->control.pmc[0].evntsel & VC3_EVNTSEL1_RESERVED)
 			return -EPERM;
-		state->k1.id = state->control.evntsel[0];
+		state->k1.id = state->control.pmc[0].evntsel;
 	} else
 		state->k1.id = 0;
 	return 0;
@@ -766,13 +766,13 @@ static int p4_check_control(struct perfc
 		/* check that pmc_map[] is well-defined;
 		   pmc_map[i] is what we pass to RDPMC, the PMC itself
 		   is extracted by masking off the FAST_RDPMC flag */
-		pmc = state->control.pmc_map[i] & ~P4_FAST_RDPMC;
-		state->pmc[i].map = state->control.pmc_map[i];
+		pmc = state->control.pmc[i].map & ~P4_FAST_RDPMC;
+		state->pmc[i].map = state->control.pmc[i].map;
 		if (pmc >= 18 || (pmc_mask & (1<<pmc)))
 			return -EINVAL;
 		pmc_mask |= (1<<pmc);
 		/* check CCCR contents */
-		cccr_val = state->control.evntsel[i];
+		cccr_val = state->control.pmc[i].evntsel;
 		if (cccr_val & P4_CCCR_RESERVED)
 			return -EPERM;
 		if (cccr_val & P4_CCCR_EXTENDED_CASCADE) {
@@ -789,14 +789,14 @@ static int p4_check_control(struct perfc
 			if (i < nractrs)
 				return -EINVAL;
 			if ((cccr_val & P4_CCCR_FORCE_OVF) &&
-			    state->control.ireset[i] != -1)
+			    state->control.pmc[i].ireset != -1)
 				return -EINVAL;
 		} else {
 			if (i >= nractrs)
 				return -EINVAL;
 		}
 		/* check ESCR contents */
-		escr_val = state->control.p4.escr[i];
+		escr_val = state->control.pmc[i].p4_escr;
 		if (escr_val & P4_ESCR_RESERVED)
 			return -EPERM;
 		if ((escr_val & P4_ESCR_CPL_T1) && (!p4_is_ht || !is_global))
@@ -855,13 +855,13 @@ static void p4_write_control(const struc
 	nrctrs = perfctr_cstatus_nrctrs(state->cstatus);
 	for(i = 0; i < nrctrs; ++i) {
 		unsigned int escr_val, escr_off, cccr_val, pmc;
-		escr_val = state->control.p4.escr[i];
+		escr_val = state->control.pmc[i].p4_escr;
 		escr_off = state->p4_escr_map[i];
 		if (escr_val != cache->control.escr[escr_off]) {
 			cache->control.escr[escr_off] = escr_val;
 			wrmsr(MSR_P4_ESCR0+escr_off, escr_val, 0);
 		}
-		cccr_val = state->control.evntsel[i];
+		cccr_val = state->control.pmc[i].evntsel;
 		pmc = state->pmc[i].map & P4_MASK_FAST_RDPMC;
 		if (cccr_val != cache->control.evntsel[pmc]) {
 			cache->control.evntsel[pmc] = cccr_val;
@@ -1004,7 +1004,7 @@ unsigned int perfctr_cpu_identify_overfl
 	for(pmc_mask = 0; pmc < nrctrs; ++pmc) {
 		if ((int)state->pmc[pmc].start >= 0) { /* XXX: ">" ? */
 			/* XXX: "+=" to correct for overshots */
-			state->pmc[pmc].start = state->control.ireset[pmc];
+			state->pmc[pmc].start = state->control.pmc[pmc].ireset;
 			pmc_mask |= (1 << pmc);
 			/* On a P4 we should now clear the OVF flag in the
 			   counter's CCCR. However, p4_isuspend() already
@@ -1024,7 +1024,7 @@ static inline int check_ireset(const str
 	i = state->control.nractrs;
 	nrctrs = i + state->control.nrictrs;
 	for(; i < nrctrs; ++i)
-		if (state->control.ireset[i] >= 0)
+		if (state->control.pmc[i].ireset >= 0)
 			return -EINVAL;
 	return 0;
 }
@@ -1036,7 +1036,7 @@ static inline void setup_imode_start_val
 	cstatus = state->cstatus;
 	nrctrs = perfctr_cstatus_nrctrs(cstatus);
 	for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
-		state->pmc[i].start = state->control.ireset[i];
+		state->pmc[i].start = state->control.pmc[i].ireset;
 }
 
 #else	/* PERFCTR_INTERRUPT_SUPPORT */
diff -puN include/asm-i386/perfctr.h~perfctr-x86-update-2 include/asm-i386/perfctr.h
--- 25/include/asm-i386/perfctr.h~perfctr-x86-update-2	2004-11-28 00:51:56.444663560 -0800
+++ 25-akpm/include/asm-i386/perfctr.h	2004-11-28 00:51:56.452662344 -0800
@@ -1,4 +1,4 @@
-/* $Id: perfctr.h,v 1.52 2004/05/23 22:36:34 mikpe Exp $
+/* $Id: perfctr.h,v 1.57 2004/11/24 00:21:20 mikpe Exp $
  * x86/x86_64 Performance-Monitoring Counters driver
  *
  * Copyright (C) 1999-2004  Mikael Pettersson
@@ -34,18 +34,20 @@ struct perfctr_cpu_control {
 	unsigned int tsc_on;
 	unsigned int nractrs;		/* # of a-mode counters */
 	unsigned int nrictrs;		/* # of i-mode counters */
-	unsigned int pmc_map[18];
-	unsigned int evntsel[18];	/* one per counter, even on P5 */
 	struct {
-		unsigned int escr[18];
 		unsigned int pebs_enable;	/* for replay tagging */
 		unsigned int pebs_matrix_vert;	/* for replay tagging */
 	} p4;
-	int ireset[18];			/* < 0, for i-mode counters */
 	unsigned int _reserved1;
 	unsigned int _reserved2;
 	unsigned int _reserved3;
 	unsigned int _reserved4;
+	struct {
+		unsigned int map;	/* for rdpmc */
+		unsigned int evntsel;	/* one per counter, even on P5 */
+		unsigned int p4_escr;
+		int ireset;		/* < 0, for i-mode counters */
+	} pmc[18];
 };
 
 struct perfctr_cpu_state {
_