Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Feb 2015 16:21:36 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r278680 - in stable/10/sys/arm: arm include
Message-ID:  <201502131621.t1DGLavv055550@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Fri Feb 13 16:21:36 2015
New Revision: 278680
URL: https://svnweb.freebsd.org/changeset/base/278680

Log:
  MFC r266083, r267597:
  
    Give suitably-endowed ARMs a register similar to the x86 TSC register.

Modified:
  stable/10/sys/arm/arm/cpufunc.c
  stable/10/sys/arm/include/cpu.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/arm/arm/cpufunc.c
==============================================================================
--- stable/10/sys/arm/arm/cpufunc.c	Fri Feb 13 16:08:45 2015	(r278679)
+++ stable/10/sys/arm/arm/cpufunc.c	Fri Feb 13 16:21:36 2015	(r278680)
@@ -1397,6 +1397,53 @@ arm10_setup(args)
 }
 #endif	/* CPU_ARM9E || CPU_ARM10 */
 
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176) \
+ || defined(CPU_MV_PJ4B) \
+ || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+static __inline void
+cpu_scc_setup_ccnt(void)
+{
+/* This is how you give userland access to the CCNT and PMCn
+ * registers.
+ * BEWARE! This gives write access also, which may not be what
+ * you want!
+ */
+#ifdef _PMC_USER_READ_WRITE_
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+	/* Use the Secure User and Non-secure Access Validation Control Register
+	 * to allow userland access
+	 */
+	__asm volatile ("mcr	p15, 0, %0, c15, c9, 0\n\t"
+			:
+			: "r"(0x00000001));
+#else
+	/* Set PMUSERENR[0] to allow userland access */
+	__asm volatile ("mcr	p15, 0, %0, c9, c14, 0\n\t"
+			:
+			: "r"(0x00000001));
+#endif
+#endif
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+	/* Set PMCR[2,0] to enable counters and reset CCNT */
+	__asm volatile ("mcr	p15, 0, %0, c15, c12, 0\n\t"
+			:
+			: "r"(0x00000005));
+#else
+	/* Set up the PMCCNTR register as a cyclecounter:
+	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
+	 * Set PMCR[2,0] to enable counters and reset CCNT
+	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
+	__asm volatile ("mcr	p15, 0, %0, c9, c14, 2\n\t"
+			"mcr	p15, 0, %1, c9, c12, 0\n\t"
+			"mcr	p15, 0, %2, c9, c12, 1\n\t"
+			:
+			: "r"(0xFFFFFFFF),
+			  "r"(0x00000005),
+			  "r"(0x80000000));
+#endif
+}
+#endif
+
 #if defined(CPU_ARM1136) || defined(CPU_ARM1176)
 struct cpu_option arm11_options[] = {
 	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
@@ -1500,6 +1547,8 @@ arm11x6_setup(char *args)
 
 	/* And again. */
 	cpu_idcache_wbinv_all();
+
+	cpu_scc_setup_ccnt();
 }
 #endif  /* CPU_ARM1136 || CPU_ARM1176 */
 
@@ -1534,6 +1583,8 @@ pj4bv7_setup(args)
 
 	/* And again. */
 	cpu_idcache_wbinv_all();
+
+	cpu_scc_setup_ccnt();
 }
 #endif /* CPU_MV_PJ4B */
 
@@ -1581,6 +1632,8 @@ cortexa_setup(char *args)
 #ifdef SMP
 	armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting  */
 #endif
+
+	cpu_scc_setup_ccnt();
 }
 #endif  /* CPU_CORTEXA */
 

Modified: stable/10/sys/arm/include/cpu.h
==============================================================================
--- stable/10/sys/arm/include/cpu.h	Fri Feb 13 16:08:45 2015	(r278679)
+++ stable/10/sys/arm/include/cpu.h	Fri Feb 13 16:21:36 2015	(r278680)
@@ -14,11 +14,35 @@ void	swi_vm(void *);
 static __inline uint64_t
 get_cyclecount(void)
 {
+/* This '#if' asks the question 'Does CP15/SCC include performance counters?' */
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176) \
+ || defined(CPU_MV_PJ4B) \
+ || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+	uint32_t ccnt;
+	uint64_t ccnt64;
+
+	/*
+	 * Read PMCCNTR. Curses! Its only 32 bits.
+	 * TODO: Fix this by catching overflow with interrupt?
+	 */
+/* The ARMv6 vs ARMv7 divide is going to need a better way of
+ * distinguishing between them.
+ */
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+	/* ARMv6 - Earlier model SCCs */
+	__asm __volatile("mrc p15, 0, %0, c15, c12, 1": "=r" (ccnt));
+#else
+	/* ARMv7 - Later model SCCs */
+	__asm __volatile("mrc p15, 0, %0, c9, c13, 0": "=r" (ccnt));
+#endif
+	ccnt64 = (uint64_t)ccnt;
+	return (ccnt64);
+#else /* No performance counters, so use binuptime(9). This is slooooow */
 	struct bintime bt;
 
 	binuptime(&bt);
 	return ((uint64_t)bt.sec << 56 | bt.frac >> 8);
-			
+#endif
 }
 #endif
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502131621.t1DGLavv055550>