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
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to