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/mips/mips/cpu.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2004 Juli Mallett.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/module.h>
   35 #include <sys/proc.h>
   36 #include <sys/stdint.h>
   37 
   38 #include <sys/bus.h>
   39 #include <sys/rman.h>
   40 #include <sys/sysctl.h>
   41 #include <sys/systm.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/vm_page.h>
   45 
   46 #include <machine/cache.h>
   47 #include <machine/cpufunc.h>
   48 #include <machine/cpuinfo.h>
   49 #include <machine/cpuregs.h>
   50 #include <machine/intr_machdep.h>
   51 #include <machine/locore.h>
   52 #include <machine/pte.h>
   53 #include <machine/tlb.h>
   54 #include <machine/hwfunc.h>
   55 #include <machine/mips_opcode.h>
   56 #include <machine/regnum.h>
   57 #include <machine/tls.h>
   58 
   59 #if defined(CPU_CNMIPS)
   60 #include <contrib/octeon-sdk/cvmx.h>
   61 #include <contrib/octeon-sdk/octeon-model.h>
   62 #endif
   63 
   64 static void cpu_identify(void);
   65 
   66 struct mips_cpuinfo cpuinfo;
   67 
   68 #define _ENCODE_INSN(a,b,c,d,e) \
   69     ((uint32_t)(((a) << 26)|((b) << 21)|((c) << 16)|((d) << 11)|(e)))
   70 
   71 #if defined(__mips_n64)
   72 
   73 #   define      _LOAD_T0_MDTLS_A1 \
   74     _ENCODE_INSN(OP_LD, A1, T0, 0, offsetof(struct thread, td_md.md_tls))
   75 
   76 #   define      _LOAD_T0_MDTLS_TCV_OFFSET_A1 \
   77     _ENCODE_INSN(OP_LD, A1, T1, 0, \
   78     offsetof(struct thread, td_md.md_tls_tcb_offset))
   79 
   80 #   define      _ADDU_V0_T0_T1 \
   81     _ENCODE_INSN(0, T0, T1, V0, OP_DADDU)
   82 
   83 #else /* mips 32 */
   84 
   85 #   define      _LOAD_T0_MDTLS_A1 \
   86     _ENCODE_INSN(OP_LW, A1, T0, 0, offsetof(struct thread, td_md.md_tls))
   87 
   88 #   define      _LOAD_T0_MDTLS_TCV_OFFSET_A1 \
   89     _ENCODE_INSN(OP_LW, A1, T1, 0, \
   90     offsetof(struct thread, td_md.md_tls_tcb_offset))
   91 
   92 #   define      _ADDU_V0_T0_T1 \
   93     _ENCODE_INSN(0, T0, T1, V0, OP_ADDU)
   94 
   95 #endif /* ! __mips_n64 */
   96 
   97 #if defined(__mips_n64) || defined(__mips_n32)
   98 
   99 #   define _MTC0_V0_USERLOCAL \
  100     _ENCODE_INSN(OP_COP0, OP_DMT, V0, 4, 2)
  101 
  102 #else /* mips o32 */
  103 
  104 #   define _MTC0_V0_USERLOCAL \
  105     _ENCODE_INSN(OP_COP0, OP_MT, V0, 4, 2)
  106 
  107 #endif /* ! (__mips_n64 || __mipsn32) */
  108 
  109 #define _JR_RA  _ENCODE_INSN(OP_SPECIAL, RA, 0, 0, OP_JR)
  110 #define _NOP    0
  111 
  112 /*
  113  * Patch cpu_switch() by removing the UserLocal register code at the end.
  114  * For MIPS hardware that don't support UserLocal Register Implementation
  115  * we remove the instructions that update this register which may cause a
  116  * reserved instruction exception in the kernel.
  117  */
  118 static void
  119 remove_userlocal_code(uint32_t *cpu_switch_code)
  120 {
  121         uint32_t *instructp;
  122 
  123         for (instructp = cpu_switch_code;; instructp++) {
  124                 if (instructp[0] == _JR_RA)
  125                         panic("%s: Unable to patch cpu_switch().", __func__);
  126                 if (instructp[0] == _LOAD_T0_MDTLS_A1 &&
  127                     instructp[1] == _LOAD_T0_MDTLS_TCV_OFFSET_A1 &&
  128                     instructp[2] == _ADDU_V0_T0_T1 &&
  129                     instructp[3] == _MTC0_V0_USERLOCAL) {
  130                         instructp[0] = _JR_RA;
  131                         instructp[1] = _NOP;
  132                         break;
  133                 }
  134         }
  135 }
  136 
  137 /*
  138  * Attempt to identify the MIPS CPU as much as possible.
  139  *
  140  * XXX: Assumes the CPU is MIPS{32,64}{,r2} compliant.
  141  * XXX: For now, skip config register selections 2 and 3
  142  * as we don't currently use L2/L3 cache or additional
  143  * MIPS32 processor features.
  144  */
  145 static void
  146 mips_get_identity(struct mips_cpuinfo *cpuinfo)
  147 {
  148         u_int32_t prid;
  149         u_int32_t cfg0;
  150         u_int32_t cfg1;
  151         u_int32_t cfg2;
  152         u_int32_t cfg3;
  153 #if defined(CPU_CNMIPS)
  154         u_int32_t cfg4;
  155 #endif
  156         u_int32_t tmp;
  157 
  158         memset(cpuinfo, 0, sizeof(struct mips_cpuinfo));
  159 
  160         /* Read and store the PrID ID for CPU identification. */
  161         prid = mips_rd_prid();
  162         cpuinfo->cpu_vendor = MIPS_PRID_CID(prid);
  163         cpuinfo->cpu_rev = MIPS_PRID_REV(prid);
  164         cpuinfo->cpu_impl = MIPS_PRID_IMPL(prid);
  165 
  166         /* Read config register selection 0 to learn TLB type. */
  167         cfg0 = mips_rd_config();
  168 
  169         cpuinfo->tlb_type = 
  170             ((cfg0 & MIPS_CONFIG0_MT_MASK) >> MIPS_CONFIG0_MT_SHIFT);
  171         cpuinfo->icache_virtual = cfg0 & MIPS_CONFIG0_VI;
  172 
  173         /* If config register selection 1 does not exist, return. */
  174         if (!(cfg0 & MIPS_CONFIG0_M))
  175                 return;
  176 
  177         /* Learn TLB size and L1 cache geometry. */
  178         cfg1 = mips_rd_config1();
  179 
  180         /* Get the Config2 and Config3 registers as well. */
  181         cfg2 = 0;
  182         cfg3 = 0;
  183         if (cfg1 & MIPS_CONFIG1_M) {
  184                 cfg2 = mips_rd_config2();
  185                 if (cfg2 & MIPS_CONFIG2_M)
  186                         cfg3 = mips_rd_config3();
  187         }
  188 
  189         /* Save FP implementation revision if FP is present. */
  190         if (cfg1 & MIPS_CONFIG1_FP)
  191                 cpuinfo->fpu_id = MipsFPID();
  192 
  193         /* Check to see if UserLocal register is implemented. */
  194         if (cfg3 & MIPS_CONFIG3_ULR) {
  195                 /* UserLocal register is implemented, enable it. */
  196                 cpuinfo->userlocal_reg = true;
  197                 tmp = mips_rd_hwrena();
  198                 mips_wr_hwrena(tmp | MIPS_HWRENA_UL);
  199         } else {
  200                 /*
  201                  * UserLocal register is not implemented. Patch
  202                  * cpu_switch() and remove unsupported code.
  203                  */
  204                 cpuinfo->userlocal_reg = false;
  205                 remove_userlocal_code((uint32_t *)cpu_switch);
  206         }
  207 
  208 
  209 #if defined(CPU_NLM)
  210         /* Account for Extended TLB entries in XLP */
  211         tmp = mips_rd_config6();
  212         cpuinfo->tlb_nentries = ((tmp >> 16) & 0xffff) + 1;
  213 #elif defined(BERI_LARGE_TLB)
  214         /* Check if we support extended TLB entries and if so activate. */
  215         tmp = mips_rd_config5();
  216 #define BERI_CP5_LTLB_SUPPORTED 0x1
  217         if (tmp & BERI_CP5_LTLB_SUPPORTED) {
  218                 /* See how many extra TLB entries we have. */
  219                 tmp = mips_rd_config6();
  220                 cpuinfo->tlb_nentries = (tmp >> 16) + 1;
  221                 /* Activate the extended entries. */
  222                 mips_wr_config6(tmp|0x4);
  223         } else
  224 #endif
  225 #if !defined(CPU_NLM)
  226         cpuinfo->tlb_nentries = 
  227             ((cfg1 & MIPS_CONFIG1_TLBSZ_MASK) >> MIPS_CONFIG1_TLBSZ_SHIFT) + 1;
  228 #endif
  229 #if defined(CPU_CNMIPS)
  230         /* Add extended TLB size information from config4.  */
  231         cfg4 = mips_rd_config4();
  232         if ((cfg4 & MIPS_CONFIG4_MMUEXTDEF) == MIPS_CONFIG4_MMUEXTDEF_MMUSIZEEXT)
  233                 cpuinfo->tlb_nentries += (cfg4 & MIPS_CONFIG4_MMUSIZEEXT) * 0x40;
  234 #endif
  235 
  236         /* L1 instruction cache. */
  237 #ifdef MIPS_DISABLE_L1_CACHE
  238         cpuinfo->l1.ic_linesize = 0;
  239 #else
  240         tmp = (cfg1 & MIPS_CONFIG1_IL_MASK) >> MIPS_CONFIG1_IL_SHIFT;
  241         if (tmp != 0) {
  242                 cpuinfo->l1.ic_linesize = 1 << (tmp + 1);
  243                 cpuinfo->l1.ic_nways = (((cfg1 & MIPS_CONFIG1_IA_MASK) >> MIPS_CONFIG1_IA_SHIFT)) + 1;
  244                 cpuinfo->l1.ic_nsets = 
  245                         1 << (((cfg1 & MIPS_CONFIG1_IS_MASK) >> MIPS_CONFIG1_IS_SHIFT) + 6);
  246         }
  247 #endif
  248 
  249         /* L1 data cache. */
  250 #ifdef MIPS_DISABLE_L1_CACHE
  251         cpuinfo->l1.dc_linesize = 0;
  252 #else
  253 #ifndef CPU_CNMIPS
  254         tmp = (cfg1 & MIPS_CONFIG1_DL_MASK) >> MIPS_CONFIG1_DL_SHIFT;
  255         if (tmp != 0) {
  256                 cpuinfo->l1.dc_linesize = 1 << (tmp + 1);
  257                 cpuinfo->l1.dc_nways = 
  258                     (((cfg1 & MIPS_CONFIG1_DA_MASK) >> MIPS_CONFIG1_DA_SHIFT)) + 1;
  259                 cpuinfo->l1.dc_nsets = 
  260                     1 << (((cfg1 & MIPS_CONFIG1_DS_MASK) >> MIPS_CONFIG1_DS_SHIFT) + 6);
  261         }
  262 #else
  263         /*
  264          * Some Octeon cache configuration parameters are by model family, not
  265          * config1.
  266          */
  267         if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
  268                 /* Octeon and Octeon XL.  */
  269                 cpuinfo->l1.dc_nsets = 1;
  270                 cpuinfo->l1.dc_nways = 64;
  271         } else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) {
  272                 /* Octeon Plus.  */
  273                 cpuinfo->l1.dc_nsets = 2;
  274                 cpuinfo->l1.dc_nways = 64;
  275         } else if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
  276                 /* Octeon II.  */
  277                 cpuinfo->l1.dc_nsets = 8;
  278                 cpuinfo->l1.dc_nways = 32;
  279 
  280                 cpuinfo->l1.ic_nsets = 8;
  281                 cpuinfo->l1.ic_nways = 37;
  282         } else {
  283                 panic("%s: unsupported Cavium Networks CPU.", __func__);
  284         }
  285 
  286         /* All Octeon models use 128 byte line size.  */
  287         cpuinfo->l1.dc_linesize = 128;
  288 #endif
  289 #endif
  290 
  291         cpuinfo->l1.ic_size = cpuinfo->l1.ic_linesize
  292             * cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_nways;
  293         cpuinfo->l1.dc_size = cpuinfo->l1.dc_linesize 
  294             * cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_nways;
  295 
  296         /*
  297          * Probe PageMask register to see what sizes of pages are supported
  298          * by writing all one's and then reading it back.
  299          */
  300         mips_wr_pagemask(~0);
  301         cpuinfo->tlb_pgmask = mips_rd_pagemask();
  302         mips_wr_pagemask(MIPS3_PGMASK_4K);
  303 
  304 #ifndef CPU_CNMIPS
  305         /* L2 cache */
  306         if (!(cfg1 & MIPS_CONFIG_CM)) {
  307                 /* We don't have valid cfg2 register */
  308                 return;
  309         }
  310 
  311         cfg2 = mips_rd_config2();
  312 
  313         tmp = (cfg2 >> MIPS_CONFIG2_SL_SHIFT) & MIPS_CONFIG2_SL_MASK;
  314         if (0 < tmp && tmp <= 7)
  315                 cpuinfo->l2.dc_linesize = 2 << tmp;
  316 
  317         tmp = (cfg2 >> MIPS_CONFIG2_SS_SHIFT) & MIPS_CONFIG2_SS_MASK;
  318         if (0 <= tmp && tmp <= 7)
  319                 cpuinfo->l2.dc_nsets = 64 << tmp;
  320 
  321         tmp = (cfg2 >> MIPS_CONFIG2_SA_SHIFT) & MIPS_CONFIG2_SA_MASK;
  322         if (0 <= tmp && tmp <= 7)
  323                 cpuinfo->l2.dc_nways = tmp + 1;
  324 
  325         cpuinfo->l2.dc_size = cpuinfo->l2.dc_linesize
  326             * cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_nways;
  327 #endif
  328 }
  329 
  330 void
  331 mips_cpu_init(void)
  332 {
  333         platform_cpu_init();
  334         mips_get_identity(&cpuinfo);
  335         num_tlbentries = cpuinfo.tlb_nentries;
  336         mips_wr_wired(0);
  337         tlb_invalidate_all();
  338         mips_wr_wired(VMWIRED_ENTRIES);
  339         mips_config_cache(&cpuinfo);
  340         mips_vector_init();
  341 
  342         mips_icache_sync_all();
  343         mips_dcache_wbinv_all();
  344         /* Print some info about CPU */
  345         cpu_identify();
  346 }
  347 
  348 static void
  349 cpu_identify(void)
  350 {
  351         uint32_t cfg0, cfg1, cfg2, cfg3;
  352 #if defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || defined (CPU_MIPS24K)
  353         uint32_t cfg7;
  354 #endif
  355         printf("cpu%d: ", 0);   /* XXX per-cpu */
  356         switch (cpuinfo.cpu_vendor) {
  357         case MIPS_PRID_CID_MTI:
  358                 printf("MIPS Technologies");
  359                 break;
  360         case MIPS_PRID_CID_BROADCOM:
  361         case MIPS_PRID_CID_SIBYTE:
  362                 printf("Broadcom");
  363                 break;
  364         case MIPS_PRID_CID_ALCHEMY:
  365                 printf("AMD");
  366                 break;
  367         case MIPS_PRID_CID_SANDCRAFT:
  368                 printf("Sandcraft");
  369                 break;
  370         case MIPS_PRID_CID_PHILIPS:
  371                 printf("Philips");
  372                 break;
  373         case MIPS_PRID_CID_TOSHIBA:
  374                 printf("Toshiba");
  375                 break;
  376         case MIPS_PRID_CID_LSI:
  377                 printf("LSI");
  378                 break;
  379         case MIPS_PRID_CID_LEXRA:
  380                 printf("Lexra");
  381                 break;
  382         case MIPS_PRID_CID_RMI:
  383                 printf("RMI");
  384                 break;
  385         case MIPS_PRID_CID_CAVIUM:
  386                 printf("Cavium");
  387                 break;
  388         case MIPS_PRID_CID_INGENIC:
  389         case MIPS_PRID_CID_INGENIC2:
  390                 printf("Ingenic XBurst");
  391                 break;
  392         case MIPS_PRID_CID_PREHISTORIC:
  393         default:
  394                 printf("Unknown cid %#x", cpuinfo.cpu_vendor);
  395                 break;
  396         }
  397         printf(" processor v%d.%d\n", cpuinfo.cpu_rev, cpuinfo.cpu_impl);
  398 
  399         printf("  MMU: ");
  400         if (cpuinfo.tlb_type == MIPS_MMU_NONE) {
  401                 printf("none present\n");
  402         } else {
  403                 if (cpuinfo.tlb_type == MIPS_MMU_TLB) {
  404                         printf("Standard TLB");
  405                 } else if (cpuinfo.tlb_type == MIPS_MMU_BAT) {
  406                         printf("Standard BAT");
  407                 } else if (cpuinfo.tlb_type == MIPS_MMU_FIXED) {
  408                         printf("Fixed mapping");
  409                 }
  410                 printf(", %d entries ", cpuinfo.tlb_nentries);
  411         }
  412 
  413         if (cpuinfo.tlb_pgmask) {
  414                 printf("(");
  415                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_MASKX)
  416                         printf("1K ");
  417                 printf("4K ");
  418                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_16K)
  419                         printf("16K ");
  420                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_64K)
  421                         printf("64K ");
  422                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_256K)
  423                         printf("256K ");
  424                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_1M)
  425                         printf("1M ");
  426                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_16M)
  427                         printf("16M ");
  428                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_64M)
  429                         printf("64M ");
  430                 if (cpuinfo.tlb_pgmask & MIPS3_PGMASK_256M)
  431                         printf("256M ");
  432                 printf("pg sizes)");
  433         }
  434         printf("\n");
  435 
  436         printf("  L1 i-cache: ");
  437         if (cpuinfo.l1.ic_linesize == 0) {
  438                 printf("disabled");
  439         } else {
  440                 if (cpuinfo.l1.ic_nways == 1) {
  441                         printf("direct-mapped with");
  442                 } else {
  443                         printf ("%d ways of", cpuinfo.l1.ic_nways);
  444                 }
  445                 printf(" %d sets, %d bytes per line\n", 
  446                     cpuinfo.l1.ic_nsets, cpuinfo.l1.ic_linesize);
  447         }
  448 
  449         printf("  L1 d-cache: ");
  450         if (cpuinfo.l1.dc_linesize == 0) {
  451                 printf("disabled");
  452         } else {
  453                 if (cpuinfo.l1.dc_nways == 1) {
  454                         printf("direct-mapped with");
  455                 } else {
  456                         printf ("%d ways of", cpuinfo.l1.dc_nways);
  457                 }
  458                 printf(" %d sets, %d bytes per line\n", 
  459                     cpuinfo.l1.dc_nsets, cpuinfo.l1.dc_linesize);
  460         }
  461 
  462         printf("  L2 cache: ");
  463         if (cpuinfo.l2.dc_linesize == 0) {
  464                 printf("disabled\n");
  465         } else {
  466                 printf("%d ways of %d sets, %d bytes per line, "
  467                     "%d KiB total size\n",
  468                     cpuinfo.l2.dc_nways,
  469                     cpuinfo.l2.dc_nsets,
  470                     cpuinfo.l2.dc_linesize,
  471                     cpuinfo.l2.dc_size / 1024);
  472         }
  473 
  474         cfg0 = mips_rd_config();
  475         /* If config register selection 1 does not exist, exit. */
  476         if (!(cfg0 & MIPS_CONFIG_CM))
  477                 return;
  478 
  479         cfg1 = mips_rd_config1();
  480         printf("  Config1=0x%b\n", cfg1, 
  481             "\2\7COP2\6MDMX\5PerfCount\4WatchRegs\3MIPS16\2EJTAG\1FPU");
  482 
  483         if (cpuinfo.fpu_id != 0)
  484                 printf("  FPU ID=0x%b\n", cpuinfo.fpu_id,
  485                     "\020"
  486                     "\020S"
  487                     "\021D"
  488                     "\022PS"
  489                     "\0233D"
  490                     "\024W"
  491                     "\025L"
  492                     "\026F64"
  493                     "\0272008"
  494                     "\034UFRP");
  495 
  496         /* If config register selection 2 does not exist, exit. */
  497         if (!(cfg1 & MIPS_CONFIG_CM))
  498                 return;
  499         cfg2 = mips_rd_config2();
  500         /* 
  501          * Config2 contains no useful information other then Config3 
  502          * existence flag
  503          */
  504         printf("  Config2=0x%08x\n", cfg2);
  505 
  506         /* If config register selection 3 does not exist, exit. */
  507         if (!(cfg2 & MIPS_CONFIG_CM))
  508                 return;
  509         cfg3 = mips_rd_config3();
  510 
  511         /* Print Config3 if it contains any useful info */
  512         if (cfg3 & ~(0x80000000))
  513                 printf("  Config3=0x%b\n", cfg3, "\2\16ULRI\2SmartMIPS\1TraceLogic");
  514 
  515 #if defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || defined (CPU_MIPS24K)
  516         cfg7 = mips_rd_config7();
  517         printf("  Config7=0x%b\n", cfg7, "\2\40WII\21AR");
  518 #endif
  519 }
  520 
  521 static struct rman cpu_hardirq_rman;
  522 
  523 static devclass_t cpu_devclass;
  524 
  525 /*
  526  * Device methods
  527  */
  528 static int cpu_probe(device_t);
  529 static int cpu_attach(device_t);
  530 static struct resource *cpu_alloc_resource(device_t, device_t, int, int *,
  531                                            rman_res_t, rman_res_t, rman_res_t,
  532                                            u_int);
  533 static int cpu_setup_intr(device_t, device_t, struct resource *, int,
  534                           driver_filter_t *f, driver_intr_t *, void *, 
  535                           void **);
  536 
  537 static device_method_t cpu_methods[] = {
  538         /* Device interface */
  539         DEVMETHOD(device_probe,         cpu_probe),
  540         DEVMETHOD(device_attach,        cpu_attach),
  541         DEVMETHOD(device_detach,        bus_generic_detach),
  542         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  543 
  544         /* Bus interface */
  545         DEVMETHOD(bus_alloc_resource,   cpu_alloc_resource),
  546         DEVMETHOD(bus_setup_intr,       cpu_setup_intr),
  547         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  548 
  549         { 0, 0 }
  550 };
  551 
  552 static driver_t cpu_driver = {
  553         "cpu", cpu_methods, 1
  554 };
  555 
  556 static int
  557 cpu_probe(device_t dev)
  558 {
  559 
  560         return (0);
  561 }
  562 
  563 static int
  564 cpu_attach(device_t dev)
  565 {
  566         int error;
  567 #ifdef notyet
  568         device_t clock;
  569 #endif
  570 
  571         cpu_hardirq_rman.rm_start = 0;
  572         cpu_hardirq_rman.rm_end = 5;
  573         cpu_hardirq_rman.rm_type = RMAN_ARRAY;
  574         cpu_hardirq_rman.rm_descr = "CPU Hard Interrupts";
  575 
  576         error = rman_init(&cpu_hardirq_rman);
  577         if (error != 0) {
  578                 device_printf(dev, "failed to initialize irq resources\n");
  579                 return (error);
  580         }
  581         /* XXX rman_manage_all. */
  582         error = rman_manage_region(&cpu_hardirq_rman,
  583                                    cpu_hardirq_rman.rm_start,
  584                                    cpu_hardirq_rman.rm_end);
  585         if (error != 0) {
  586                 device_printf(dev, "failed to manage irq resources\n");
  587                 return (error);
  588         }
  589 
  590         if (device_get_unit(dev) != 0)
  591                 panic("can't attach more cpus");
  592         device_set_desc(dev, "MIPS32 processor");
  593 
  594 #ifdef notyet
  595         clock = device_add_child(dev, "clock", device_get_unit(dev));
  596         if (clock == NULL)
  597                 device_printf(dev, "clock failed to attach");
  598 #endif
  599 
  600         return (bus_generic_attach(dev));
  601 }
  602 
  603 static struct resource *
  604 cpu_alloc_resource(device_t dev, device_t child, int type, int *rid,
  605                    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
  606 {
  607         struct resource *res;
  608 
  609         if (type != SYS_RES_IRQ)
  610                 return (NULL);
  611         res = rman_reserve_resource(&cpu_hardirq_rman, start, end, count, 0,
  612                                     child);
  613         return (res);
  614 }
  615 
  616 static int
  617 cpu_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
  618                driver_filter_t *filt, driver_intr_t *handler, void *arg, 
  619                void **cookiep)
  620 {
  621         int error;
  622         int intr;
  623 
  624         error = rman_activate_resource(res);
  625         if (error != 0) {
  626                 device_printf(child, "could not activate irq\n");
  627                 return (error);
  628         }
  629 
  630         intr = rman_get_start(res);
  631 
  632         cpu_establish_hardintr(device_get_nameunit(child), filt, handler, arg, 
  633             intr, flags, cookiep);
  634         device_printf(child, "established CPU interrupt %d\n", intr);
  635         return (0);
  636 }
  637 
  638 DRIVER_MODULE(cpu, root, cpu_driver, cpu_devclass, 0, 0);

Cache object: 64d5d8fe163acebd5f7eed02e182d88c


[ 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.