Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Jul 2015 11:32:30 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285311 - in head/sys/arm64: arm64 include
Message-ID:  <201507091132.t69BWU3Z094067@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zbb
Date: Thu Jul  9 11:32:29 2015
New Revision: 285311
URL: https://svnweb.freebsd.org/changeset/base/285311

Log:
  Rework CPU identification on ARM64
  
  This commit reworks the code responsible for identification of
  the CPUs during runtime.
  It is necessary to provide a way for workarounds and erratums
  to be applied only for certain HW versions.
  
  The copy of MIDR is now stored in pcpu to provide a fast and
  convenient way for assambly code to read it (pcpu is used quite often
  so there is a chance it's inside the cache).
  The MIDR is also better way of identification than using user-friendly
  cpu_desc structure, because it can be compiled into comparision of
  single u32 with only one access to the memory - this is crucial
  for some erratums which are called from performance-critical
  places.
  
  Changes in cpu_identify makes this function safe to be called
  on non-boot CPUs.
  
  New function CPU_MATCH was implemented which returns boolean
  value based on mathing masked MIDR with chip identification.
  Example of usage:
  
  printf("is thunder: %d\n", CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
          CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0));
  printf("is generic: %d\n", CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
          CPU_IMPL_ARM, CPU_PART_FOUNDATION, 0, 0));
  
  Reviewed by:   andrew
  Obtained from: Semihalf
  Sponsored by:  The FreeBSD Foundation
  Differential Revision: https://reviews.freebsd.org/D3030

Modified:
  head/sys/arm64/arm64/identcpu.c
  head/sys/arm64/include/cpu.h
  head/sys/arm64/include/pcpu.h

Modified: head/sys/arm64/arm64/identcpu.c
==============================================================================
--- head/sys/arm64/arm64/identcpu.c	Thu Jul  9 09:22:21 2015	(r285310)
+++ head/sys/arm64/arm64/identcpu.c	Thu Jul  9 11:32:29 2015	(r285311)
@@ -48,7 +48,7 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, 
 /*
  * Per-CPU affinity as provided in MPIDR_EL1
  * Indexed by CPU number in logical order selected by the system.
- * Relevant fields can be extracetd using CPU_AFFn macros,
+ * Relevant fields can be extracted using CPU_AFFn macros,
  * Aff3.Aff2.Aff1.Aff0 construct a unique CPU address in the system.
  *
  * Fields used by us:
@@ -57,28 +57,6 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, 
  */
 uint64_t __cpu_affinity[MAXCPU];
 
-#define	CPU_IMPL_ARM		0x41
-#define	CPU_IMPL_BROADCOM	0x42
-#define	CPU_IMPL_CAVIUM		0x43
-#define	CPU_IMPL_DEC		0x44
-#define	CPU_IMPL_INFINEON	0x49
-#define	CPU_IMPL_FREESCALE	0x4D
-#define	CPU_IMPL_NVIDIA		0x4E
-#define	CPU_IMPL_APM		0x50
-#define	CPU_IMPL_QUALCOMM	0x51
-#define	CPU_IMPL_MARVELL	0x56
-#define	CPU_IMPL_INTEL		0x69
-
-#define	CPU_PART_THUNDER	0x0A1
-#define	CPU_PART_FOUNDATION	0xD00
-#define	CPU_PART_CORTEX_A53	0xD03
-#define	CPU_PART_CORTEX_A57	0xD07
-
-#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
-#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
-#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
-#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
-
 struct cpu_desc {
 	u_int		cpu_impl;
 	u_int		cpu_part_num;
@@ -112,14 +90,14 @@ struct cpu_implementers {
  */
 /* ARM Ltd. */
 static const struct cpu_parts cpu_parts_arm[] = {
-	{ 0xD00, "Foundation-Model" },
-	{ 0xD03, "Cortex-A53" },
-	{ 0xD07, "Cortex-A57" },
+	{ CPU_PART_FOUNDATION, "Foundation-Model" },
+	{ CPU_PART_CORTEX_A53, "Cortex-A53" },
+	{ CPU_PART_CORTEX_A57, "Cortex-A57" },
 	CPU_PART_NONE,
 };
 /* Cavium */
 static const struct cpu_parts cpu_parts_cavium[] = {
-	{ 0x0A1, "Thunder" },
+	{ CPU_PART_THUNDER, "Thunder" },
 	CPU_PART_NONE,
 };
 
@@ -162,6 +140,12 @@ identify_cpu(void)
 	cpu = PCPU_GET(cpuid);
 	midr = get_midr();
 
+	/*
+	 * Store midr to pcpu to allow fast reading
+	 * from EL0, EL1 and assembly code.
+	 */
+	PCPU_SET(midr, midr);
+
 	impl_id = CPU_IMPL(midr);
 	for (i = 0; i < nitems(cpu_implementers); i++) {
 		if (impl_id == cpu_implementers[i].impl_id ||
@@ -183,15 +167,21 @@ identify_cpu(void)
 		}
 	}
 
-	printf("CPU: %s %s r%dp%d\n", cpu_desc[cpu].cpu_impl_name,
-	    cpu_desc[cpu].cpu_part_name, CPU_VAR(midr), CPU_REV(midr));
+	cpu_desc[cpu].cpu_revision = CPU_REV(midr);
+	cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
 
-	/*
-	 * Save affinity for the boot CPU.
-	 * (CPU0 in the internal system enumeration.
-	 */
+	/* Save affinity for current CPU */
 	mpidr = get_mpidr();
-	CPU_AFFINITY(0) = mpidr & CPU_AFF_MASK;
+	CPU_AFFINITY(cpu) = mpidr & CPU_AFF_MASK;
+
+	/* Print details for boot CPU or if we want verbose output */
+	if (cpu == 0 || bootverbose) {
+		printf("CPU(%d): %s %s r%dp%d\n", cpu,
+		    cpu_desc[cpu].cpu_impl_name,
+		    cpu_desc[cpu].cpu_part_name,
+		    cpu_desc[cpu].cpu_variant,
+		    cpu_desc[cpu].cpu_revision);
+	}
 
 	if (bootverbose)
 		printf("CPU%u affinity: %u.%u.%u.%u\n", 0, CPU_AFF0(mpidr),

Modified: head/sys/arm64/include/cpu.h
==============================================================================
--- head/sys/arm64/include/cpu.h	Thu Jul  9 09:22:21 2015	(r285310)
+++ head/sys/arm64/include/cpu.h	Thu Jul  9 11:32:29 2015	(r285311)
@@ -60,6 +60,43 @@
 
 #ifdef _KERNEL
 
+#define	CPU_IMPL_ARM		0x41
+#define	CPU_IMPL_BROADCOM	0x42
+#define	CPU_IMPL_CAVIUM		0x43
+#define	CPU_IMPL_DEC		0x44
+#define	CPU_IMPL_INFINEON	0x49
+#define	CPU_IMPL_FREESCALE	0x4D
+#define	CPU_IMPL_NVIDIA		0x4E
+#define	CPU_IMPL_APM		0x50
+#define	CPU_IMPL_QUALCOMM	0x51
+#define	CPU_IMPL_MARVELL	0x56
+#define	CPU_IMPL_INTEL		0x69
+
+#define	CPU_PART_THUNDER	0x0A1
+#define	CPU_PART_FOUNDATION	0xD00
+#define	CPU_PART_CORTEX_A53	0xD03
+#define	CPU_PART_CORTEX_A57	0xD07
+
+#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
+#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
+#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
+#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+
+#define	CPU_IMPL_TO_MIDR(val)	(((val) & 0xff) << 24)
+#define	CPU_PART_TO_MIDR(val)	(((val) & 0xfff) << 4)
+#define	CPU_VAR_TO_MIDR(val)	(((val) & 0xf) << 20)
+#define	CPU_REV_TO_MIDR(val)	(((val) & 0xf) << 0)
+
+#define	CPU_IMPL_MASK	(0xff << 24)
+#define	CPU_PART_MASK	(0xfff << 4)
+#define	CPU_VAR_MASK	(0xf << 20)
+#define	CPU_REV_MASK	(0xf << 0)
+
+#define CPU_MATCH(mask, impl, part, var, rev)						\
+    (((mask) & PCPU_GET(midr)) == (CPU_IMPL_TO_MIDR((impl)) |		\
+    CPU_PART_TO_MIDR((part)) | CPU_VAR_TO_MIDR((var)) |				\
+    CPU_REV_TO_MIDR((rev))))
+
 extern char btext[];
 extern char etext[];
 

Modified: head/sys/arm64/include/pcpu.h
==============================================================================
--- head/sys/arm64/include/pcpu.h	Thu Jul  9 09:22:21 2015	(r285310)
+++ head/sys/arm64/include/pcpu.h	Thu Jul  9 11:32:29 2015	(r285311)
@@ -36,8 +36,9 @@
 #define	ALT_STACK_SIZE	128
 
 #define	PCPU_MD_FIELDS							\
-	u_int	pc_acpi_id;	/* ACPI CPU id */			\
-	char __pad[125]
+	u_int	pc_acpi_id;	/* ACPI CPU id */		\
+	u_int	pc_midr;	/* stored MIDR value */	\
+	char __pad[121]
 
 #ifdef _KERNEL
 



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