The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/arm/identcpu-v6.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1995 Mark Brinicombe.
    5  * Copyright (c) 1995 Brini.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Brini.
   19  * 4. The name of the company nor the name of the author may be used to
   20  *    endorse or promote products derived from this software without specific
   21  *    prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
   24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   26  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  * RiscBSD kernel project
   36  *
   37  * cpu.c
   38  *
   39  * Probing and configuration for the master CPU
   40  *
   41  * Created      : 10/10/95
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD$");
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/conf.h>
   49 #include <sys/kernel.h>
   50 #include <sys/sysctl.h>
   51 #include <machine/cpu.h>
   52 #include <machine/md_var.h>
   53 
   54 char machine[] = "arm";
   55 
   56 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
   57         machine, 0, "Machine class");
   58 
   59 static char cpu_model[64];
   60 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD,
   61     cpu_model, sizeof(cpu_model), "Machine model");
   62 
   63 static char hw_buf[81];
   64 static int hw_buf_idx;
   65 static bool hw_buf_newline;
   66 
   67 enum cpu_class cpu_class = CPU_CLASS_NONE;
   68 
   69 static struct {
   70         int     implementer;
   71         int     part_number;
   72         char    *impl_name;
   73         char    *core_name;
   74         enum    cpu_class cpu_class;
   75 } cpu_names[] =  {
   76         {CPU_IMPLEMENTER_ARM, CPU_ARCH_ARM1176,    "ARM", "ARM1176",
   77             CPU_CLASS_ARM11J},
   78         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A5 , "ARM", "Cortex-A5",
   79             CPU_CLASS_CORTEXA},
   80         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A7 , "ARM", "Cortex-A7",
   81             CPU_CLASS_CORTEXA},
   82         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A8 , "ARM", "Cortex-A8",
   83             CPU_CLASS_CORTEXA},
   84         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A9 , "ARM", "Cortex-A9",
   85             CPU_CLASS_CORTEXA},
   86         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A12, "ARM", "Cortex-A12",
   87             CPU_CLASS_CORTEXA},
   88         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A15, "ARM", "Cortex-A15",
   89             CPU_CLASS_CORTEXA},
   90         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A17, "ARM", "Cortex-A17",
   91             CPU_CLASS_CORTEXA},
   92         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A53, "ARM", "Cortex-A53",
   93             CPU_CLASS_CORTEXA},
   94         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A57, "ARM", "Cortex-A57",
   95             CPU_CLASS_CORTEXA},
   96         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A72, "ARM", "Cortex-A72",
   97             CPU_CLASS_CORTEXA},
   98         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A73, "ARM", "Cortex-A73",
   99             CPU_CLASS_CORTEXA},
  100 
  101         {CPU_IMPLEMENTER_MRVL, CPU_ARCH_SHEEVA_581, "Marvell", "PJ4 v7",
  102             CPU_CLASS_MARVELL},
  103         {CPU_IMPLEMENTER_MRVL, CPU_ARCH_SHEEVA_584, "Marvell", "PJ4MP v7",
  104             CPU_CLASS_MARVELL},
  105 
  106         {CPU_IMPLEMENTER_QCOM, CPU_ARCH_KRAIT_300, "Qualcomm", "Krait 300",
  107             CPU_CLASS_KRAIT},
  108 };
  109 
  110 static void
  111 print_v5_cache(void)
  112 {
  113         uint32_t isize, dsize;
  114         uint32_t multiplier;
  115         int pcache_type;
  116         int pcache_unified;
  117         int picache_size;
  118         int picache_line_size;
  119         int picache_ways;
  120         int pdcache_size;
  121         int pdcache_line_size;
  122         int pdcache_ways;
  123 
  124         pcache_unified = 0;
  125         picache_size = 0 ;
  126         picache_line_size = 0 ;
  127         picache_ways = 0 ;
  128         pdcache_size = 0;
  129         pdcache_line_size = 0;
  130         pdcache_ways = 0;
  131 
  132         if ((cpuinfo.ctr & CPU_CT_S) == 0)
  133                 pcache_unified = 1;
  134 
  135         /*
  136          * If you want to know how this code works, go read the ARM ARM.
  137          */
  138         pcache_type = CPU_CT_CTYPE(cpuinfo.ctr);
  139 
  140         if (pcache_unified == 0) {
  141                 isize = CPU_CT_ISIZE(cpuinfo.ctr);
  142                 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
  143                 picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
  144                 if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
  145                         if (isize & CPU_CT_xSIZE_M)
  146                                 picache_line_size = 0; /* not present */
  147                         else
  148                                 picache_ways = 1;
  149                 } else {
  150                         picache_ways = multiplier <<
  151                             (CPU_CT_xSIZE_ASSOC(isize) - 1);
  152                 }
  153                 picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
  154         }
  155 
  156         dsize = CPU_CT_DSIZE(cpuinfo.ctr);
  157         multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
  158         pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
  159         if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
  160                 if (dsize & CPU_CT_xSIZE_M)
  161                         pdcache_line_size = 0; /* not present */
  162                 else
  163                         pdcache_ways = 1;
  164         } else {
  165                 pdcache_ways = multiplier <<
  166                     (CPU_CT_xSIZE_ASSOC(dsize) - 1);
  167                 }
  168         pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
  169 
  170         /* Print cache info. */
  171         if (picache_line_size == 0 && pdcache_line_size == 0)
  172                 return;
  173 
  174         if (pcache_unified) {
  175                 printf("  %dKB/%dB %d-way %s unified cache\n",
  176                     pdcache_size / 1024,
  177                     pdcache_line_size, pdcache_ways,
  178                     pcache_type == 0 ? "WT" : "WB");
  179         } else {
  180                 printf("  %dKB/%dB %d-way instruction cache\n",
  181                     picache_size / 1024,
  182                     picache_line_size, picache_ways);
  183                 printf("  %dKB/%dB %d-way %s data cache\n",
  184                     pdcache_size / 1024,
  185                     pdcache_line_size, pdcache_ways,
  186                     pcache_type == 0 ? "WT" : "WB");
  187         }
  188 }
  189 
  190 static void
  191 print_v7_cache(void )
  192 {
  193         uint32_t type, val, size, sets, ways, linesize;
  194         int i;
  195 
  196         printf("LoUU:%d LoC:%d LoUIS:%d \n",
  197             CPU_CLIDR_LOUU(cpuinfo.clidr) + 1,
  198             CPU_CLIDR_LOC(cpuinfo.clidr) + 1,
  199             CPU_CLIDR_LOUIS(cpuinfo.clidr) + 1);
  200 
  201         for (i = 0; i < 7; i++) {
  202                 type = CPU_CLIDR_CTYPE(cpuinfo.clidr, i);
  203                 if (type == 0)
  204                         break;
  205                 printf("Cache level %d:\n", i + 1);
  206                 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
  207                     type == CACHE_SEP_CACHE) {
  208                         cp15_csselr_set(i << 1);
  209                         val = cp15_ccsidr_get();
  210                         ways = CPUV7_CT_xSIZE_ASSOC(val) + 1;
  211                         sets = CPUV7_CT_xSIZE_SET(val) + 1;
  212                         linesize = 1 << (CPUV7_CT_xSIZE_LEN(val) + 4);
  213                         size = (ways * sets * linesize) / 1024;
  214 
  215                         if (type == CACHE_UNI_CACHE)
  216                                 printf(" %dKB/%dB %d-way unified cache",
  217                                     size, linesize,ways);
  218                         else
  219                                 printf(" %dKB/%dB %d-way data cache",
  220                                     size, linesize, ways);
  221                         if (val & CPUV7_CT_CTYPE_WT)
  222                                 printf(" WT");
  223                         if (val & CPUV7_CT_CTYPE_WB)
  224                                 printf(" WB");
  225                         if (val & CPUV7_CT_CTYPE_RA)
  226                                 printf(" Read-Alloc");
  227                         if (val & CPUV7_CT_CTYPE_WA)
  228                                 printf(" Write-Alloc");
  229                         printf("\n");
  230                 }
  231 
  232                 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
  233                         cp15_csselr_set(i << 1 | 1);
  234                         val = cp15_ccsidr_get();
  235                         ways = CPUV7_CT_xSIZE_ASSOC(val) + 1;
  236                         sets = CPUV7_CT_xSIZE_SET(val) + 1;
  237                         linesize = 1 << (CPUV7_CT_xSIZE_LEN(val) + 4);
  238                         size = (ways * sets * linesize) / 1024;
  239                                 printf(" %dKB/%dB %d-way instruction cache",
  240                             size, linesize, ways);
  241                         if (val & CPUV7_CT_CTYPE_WT)
  242                                 printf(" WT");
  243                         if (val & CPUV7_CT_CTYPE_WB)
  244                                 printf(" WB");
  245                         if (val & CPUV7_CT_CTYPE_RA)
  246                                 printf(" Read-Alloc");
  247                         if (val & CPUV7_CT_CTYPE_WA)
  248                                 printf(" Write-Alloc");
  249                         printf("\n");
  250                 }
  251         }
  252         cp15_csselr_set(0);
  253 }
  254 
  255 static void
  256 add_cap(char *cap)
  257 {
  258         int len;
  259 
  260         len = strlen(cap);
  261 
  262         if ((hw_buf_idx + len + 2) >= 79) {
  263                 printf("%s,\n", hw_buf);
  264                 hw_buf_idx  = 0;
  265                 hw_buf_newline = true;
  266         }
  267         if (hw_buf_newline)
  268                 hw_buf_idx += sprintf(hw_buf + hw_buf_idx, "  ");
  269         else
  270                 hw_buf_idx += sprintf(hw_buf + hw_buf_idx, ", ");
  271         hw_buf_newline = false;
  272 
  273         hw_buf_idx += sprintf(hw_buf + hw_buf_idx, "%s", cap);
  274 }
  275 
  276 void
  277 identify_arm_cpu(void)
  278 {
  279         int i;
  280         u_int val;
  281 
  282         /*
  283          * CPU
  284          */
  285         for(i = 0; i < nitems(cpu_names); i++) {
  286                 if (cpu_names[i].implementer == cpuinfo.implementer &&
  287                     cpu_names[i].part_number == cpuinfo.part_number) {
  288                         cpu_class = cpu_names[i].cpu_class;
  289                         snprintf(cpu_model, sizeof(cpu_model),
  290                             "%s %s r%dp%d (ECO: 0x%08X)",
  291                             cpu_names[i].impl_name, cpu_names[i].core_name,
  292                             cpuinfo.revision, cpuinfo.patch,
  293                             cpuinfo.midr != cpuinfo.revidr ?
  294                             cpuinfo.revidr : 0);
  295                         printf("CPU: %s\n", cpu_model);
  296                         break;
  297                 }
  298         }
  299         if (i >= nitems(cpu_names))
  300                 printf("unknown CPU (ID = 0x%x)\n", cpuinfo.midr);
  301 
  302         printf("CPU Features: \n");
  303         hw_buf_idx = 0;
  304         hw_buf_newline = true;
  305 
  306         val = (cpuinfo.mpidr >> 4)& 0xF;
  307         if (cpuinfo.mpidr & (1 << 31U))
  308                 add_cap("Multiprocessing");
  309         val = (cpuinfo.id_pfr0 >> 4)& 0xF;
  310         if (val == 1)
  311                 add_cap("Thumb");
  312         else if (val == 3)
  313                 add_cap("Thumb2");
  314 
  315         val = (cpuinfo.id_pfr1 >> 4)& 0xF;
  316         if (val == 1 || val == 2)
  317                 add_cap("Security");
  318 
  319         val = (cpuinfo.id_pfr1 >> 12)& 0xF;
  320         if (val == 1)
  321                 add_cap("Virtualization");
  322 
  323         val = (cpuinfo.id_pfr1 >> 16)& 0xF;
  324         if (val == 1)
  325                 add_cap("Generic Timer");
  326 
  327         val = (cpuinfo.id_mmfr0 >> 0)& 0xF;
  328         if (val == 2) {
  329                 add_cap("VMSAv6");
  330         } else if (val >= 3) {
  331                 add_cap("VMSAv7");
  332                 if (val >= 4)
  333                         add_cap("PXN");
  334                 if (val >= 5)
  335                         add_cap("LPAE");
  336         }
  337 
  338         val = (cpuinfo.id_mmfr3 >> 20)& 0xF;
  339         if (val == 1)
  340                 add_cap("Coherent Walk");
  341 
  342         if (hw_buf_idx != 0)
  343                 printf("%s\n", hw_buf);
  344 
  345         printf("Optional instructions: \n");
  346         hw_buf_idx = 0;
  347         hw_buf_newline = true;
  348         val = (cpuinfo.id_isar0 >> 24)& 0xF;
  349         if (val == 1)
  350                 add_cap("SDIV/UDIV (Thumb)");
  351         else if (val == 2)
  352                 add_cap("SDIV/UDIV");
  353 
  354         val = (cpuinfo.id_isar2 >> 20)& 0xF;
  355         if (val == 1 || val == 2)
  356                 add_cap("UMULL");
  357 
  358         val = (cpuinfo.id_isar2 >> 16)& 0xF;
  359         if (val == 1 || val == 2 || val == 3)
  360                 add_cap("SMULL");
  361 
  362         val = (cpuinfo.id_isar2 >> 12)& 0xF;
  363         if (val == 1)
  364                 add_cap("MLA");
  365 
  366         val = (cpuinfo.id_isar3 >> 4)& 0xF;
  367         if (val == 1)
  368                 add_cap("SIMD");
  369         else if (val == 3)
  370                 add_cap("SIMD(ext)");
  371         if (hw_buf_idx != 0)
  372                 printf("%s\n", hw_buf);
  373 
  374         /*
  375          * Cache
  376          */
  377         if (CPU_CT_FORMAT(cpuinfo.ctr) == CPU_CT_ARMV7)
  378                 print_v7_cache();
  379         else
  380                 print_v5_cache();
  381 }

Cache object: e74f28d7cafebc423bf0f1b2c1cd8ce9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.