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/powerpc/aim/mp_cpudep.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  * Copyright (c) 2008 Marcel Moolenaar
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    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 ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bus.h>
   34 #include <sys/pcpu.h>
   35 #include <sys/proc.h>
   36 #include <sys/smp.h>
   37 
   38 #include <machine/bus.h>
   39 #include <machine/cpu.h>
   40 #include <machine/hid.h>
   41 #include <machine/intr_machdep.h>
   42 #include <machine/pcb.h>
   43 #include <machine/psl.h>
   44 #include <machine/smp.h>
   45 #include <machine/spr.h>
   46 #include <machine/trap_aim.h>
   47 
   48 #include <dev/ofw/openfirm.h>
   49 #include <machine/ofw_machdep.h>
   50 
   51 void *ap_pcpu;
   52 
   53 static register_t bsp_state[8] __aligned(8);
   54 
   55 static void cpudep_save_config(void *dummy);
   56 SYSINIT(cpu_save_config, SI_SUB_CPU, SI_ORDER_ANY, cpudep_save_config, NULL);
   57 
   58 void
   59 cpudep_ap_early_bootstrap(void)
   60 {
   61         register_t reg;
   62 
   63         __asm __volatile("mtsprg 0, %0" :: "r"(ap_pcpu));
   64         powerpc_sync();
   65 
   66         switch (mfpvr() >> 16) {
   67         case IBM970:
   68         case IBM970FX:
   69         case IBM970MP:
   70                 /* Restore HID4 and HID5, which are necessary for the MMU */
   71 
   72                 __asm __volatile("ld %0, 16(%2); sync; isync;   \
   73                     mtspr %1, %0; sync; isync;"
   74                     : "=r"(reg) : "K"(SPR_HID4), "r"(bsp_state));
   75                 __asm __volatile("ld %0, 24(%2); sync; isync;   \
   76                     mtspr %1, %0; sync; isync;"
   77                     : "=r"(reg) : "K"(SPR_HID5), "r"(bsp_state));
   78                 powerpc_sync();
   79                 break;
   80         }
   81 }
   82 
   83 uintptr_t
   84 cpudep_ap_bootstrap(void)
   85 {
   86         register_t msr, sp;
   87 
   88         msr = PSL_KERNSET & ~PSL_EE;
   89         mtmsr(msr);
   90 
   91         curthread_reg = pcpup->pc_curthread = pcpup->pc_idlethread;
   92         pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb;
   93         sp = pcpup->pc_curpcb->pcb_sp;
   94 
   95         return (sp);
   96 }
   97 
   98 static register_t
   99 mpc74xx_l2_enable(register_t l2cr_config)
  100 {
  101         register_t ccr, bit;
  102         uint16_t        vers;
  103 
  104         vers = mfpvr() >> 16;
  105         switch (vers) {
  106         case MPC7400:
  107         case MPC7410:
  108                 bit = L2CR_L2IP;
  109                 break;
  110         default:
  111                 bit = L2CR_L2I;
  112                 break;
  113         }
  114 
  115         ccr = mfspr(SPR_L2CR);
  116         if (ccr & L2CR_L2E)
  117                 return (ccr);
  118 
  119         /* Configure L2 cache. */
  120         ccr = l2cr_config & ~L2CR_L2E;
  121         mtspr(SPR_L2CR, ccr | L2CR_L2I);
  122         do {
  123                 ccr = mfspr(SPR_L2CR);
  124         } while (ccr & bit);
  125         powerpc_sync();
  126         mtspr(SPR_L2CR, l2cr_config);
  127         powerpc_sync();
  128 
  129         return (l2cr_config);
  130 }
  131 
  132 static register_t
  133 mpc745x_l3_enable(register_t l3cr_config)
  134 {
  135         register_t ccr;
  136 
  137         ccr = mfspr(SPR_L3CR);
  138         if (ccr & L3CR_L3E)
  139                 return (ccr);
  140 
  141         /* Configure L3 cache. */
  142         ccr = l3cr_config & ~(L3CR_L3E | L3CR_L3I | L3CR_L3PE | L3CR_L3CLKEN);
  143         mtspr(SPR_L3CR, ccr);
  144         ccr |= 0x4000000;       /* Magic, but documented. */
  145         mtspr(SPR_L3CR, ccr);
  146         ccr |= L3CR_L3CLKEN;
  147         mtspr(SPR_L3CR, ccr);
  148         mtspr(SPR_L3CR, ccr | L3CR_L3I);
  149         while (mfspr(SPR_L3CR) & L3CR_L3I)
  150                 ;
  151         mtspr(SPR_L3CR, ccr & ~L3CR_L3CLKEN);
  152         powerpc_sync();
  153         DELAY(100);
  154         mtspr(SPR_L3CR, ccr);
  155         powerpc_sync();
  156         DELAY(100);
  157         ccr |= L3CR_L3E;
  158         mtspr(SPR_L3CR, ccr);
  159         powerpc_sync();
  160 
  161         return(ccr);
  162 }
  163 
  164 static register_t
  165 mpc74xx_l1d_enable(void)
  166 {
  167         register_t hid;
  168 
  169         hid = mfspr(SPR_HID0);
  170         if (hid & HID0_DCE)
  171                 return (hid);
  172 
  173         /* Enable L1 D-cache */
  174         hid |= HID0_DCE;
  175         powerpc_sync();
  176         mtspr(SPR_HID0, hid | HID0_DCFI);
  177         powerpc_sync();
  178 
  179         return (hid);
  180 }
  181 
  182 static register_t
  183 mpc74xx_l1i_enable(void)
  184 {
  185         register_t hid;
  186 
  187         hid = mfspr(SPR_HID0);
  188         if (hid & HID0_ICE)
  189                 return (hid);
  190 
  191         /* Enable L1 I-cache */
  192         hid |= HID0_ICE;
  193         isync();
  194         mtspr(SPR_HID0, hid | HID0_ICFI);
  195         isync();
  196 
  197         return (hid);
  198 }
  199 
  200 static void
  201 cpudep_save_config(void *dummy)
  202 {
  203         uint16_t        vers;
  204 
  205         vers = mfpvr() >> 16;
  206 
  207         switch(vers) {
  208         case IBM970:
  209         case IBM970FX:
  210         case IBM970MP:
  211                 #ifdef __powerpc64__
  212                 bsp_state[0] = mfspr(SPR_HID0);
  213                 bsp_state[1] = mfspr(SPR_HID1);
  214                 bsp_state[2] = mfspr(SPR_HID4);
  215                 bsp_state[3] = mfspr(SPR_HID5);
  216                 #else
  217                 __asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
  218                     : "=r" (bsp_state[0]),"=r" (bsp_state[1]) : "K" (SPR_HID0));
  219                 __asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
  220                     : "=r" (bsp_state[2]),"=r" (bsp_state[3]) : "K" (SPR_HID1));
  221                 __asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
  222                     : "=r" (bsp_state[4]),"=r" (bsp_state[5]) : "K" (SPR_HID4));
  223                 __asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
  224                     : "=r" (bsp_state[6]),"=r" (bsp_state[7]) : "K" (SPR_HID5));
  225                 #endif
  226 
  227                 powerpc_sync();
  228 
  229                 break;
  230         case IBMCELLBE:
  231                 #ifdef NOTYET /* Causes problems if in instruction stream on 970 */
  232                 if (mfmsr() & PSL_HV) {
  233                         bsp_state[0] = mfspr(SPR_HID0);
  234                         bsp_state[1] = mfspr(SPR_HID1);
  235                         bsp_state[2] = mfspr(SPR_HID4);
  236                         bsp_state[3] = mfspr(SPR_HID6);
  237 
  238                         bsp_state[4] = mfspr(SPR_CELL_TSCR);
  239                 }
  240                 #endif
  241 
  242                 bsp_state[5] = mfspr(SPR_CELL_TSRL);
  243 
  244                 break;
  245         case MPC7450:
  246         case MPC7455:
  247         case MPC7457:
  248                 /* Only MPC745x CPUs have an L3 cache. */
  249                 bsp_state[3] = mfspr(SPR_L3CR);
  250 
  251                 /* Fallthrough */
  252         case MPC7400:
  253         case MPC7410:
  254         case MPC7447A:
  255         case MPC7448:
  256                 bsp_state[2] = mfspr(SPR_L2CR);
  257                 bsp_state[1] = mfspr(SPR_HID1);
  258                 bsp_state[0] = mfspr(SPR_HID0);
  259                 break;
  260         }
  261 }
  262 
  263 void
  264 cpudep_ap_setup()
  265 { 
  266         register_t      reg;
  267         uint16_t        vers;
  268 
  269         vers = mfpvr() >> 16;
  270 
  271         switch(vers) {
  272         case IBM970:
  273         case IBM970FX:
  274         case IBM970MP:
  275                 /* Set HIOR to 0 */
  276                 __asm __volatile("mtspr 311,%0" :: "r"(0));
  277                 powerpc_sync();
  278 
  279                 /*
  280                  * The 970 has strange rules about how to update HID registers.
  281                  * See Table 2-3, 970MP manual
  282                  */
  283 
  284                 __asm __volatile("mtasr %0; sync" :: "r"(0));
  285                 __asm __volatile(" \
  286                         ld      %0,0(%2);                               \
  287                         sync; isync;                                    \
  288                         mtspr   %1, %0;                                 \
  289                         mfspr   %0, %1; mfspr   %0, %1; mfspr   %0, %1; \
  290                         mfspr   %0, %1; mfspr   %0, %1; mfspr   %0, %1; \
  291                         sync; isync" 
  292                     : "=r"(reg) : "K"(SPR_HID0), "r"(bsp_state));
  293                 __asm __volatile("ld %0, 8(%2); sync; isync;    \
  294                     mtspr %1, %0; mtspr %1, %0; sync; isync"
  295                     : "=r"(reg) : "K"(SPR_HID1), "r"(bsp_state));
  296                 __asm __volatile("ld %0, 16(%2); sync; isync;   \
  297                     mtspr %1, %0; sync; isync;"
  298                     : "=r"(reg) : "K"(SPR_HID4), "r"(bsp_state));
  299                 __asm __volatile("ld %0, 24(%2); sync; isync;   \
  300                     mtspr %1, %0; sync; isync;"
  301                     : "=r"(reg) : "K"(SPR_HID5), "r"(bsp_state));
  302 
  303                 powerpc_sync();
  304                 break;
  305         case IBMCELLBE:
  306                 #ifdef NOTYET /* Causes problems if in instruction stream on 970 */
  307                 if (mfmsr() & PSL_HV) {
  308                         mtspr(SPR_HID0, bsp_state[0]);
  309                         mtspr(SPR_HID1, bsp_state[1]);
  310                         mtspr(SPR_HID4, bsp_state[2]);
  311                         mtspr(SPR_HID6, bsp_state[3]);
  312 
  313                         mtspr(SPR_CELL_TSCR, bsp_state[4]);
  314                 }
  315                 #endif
  316 
  317                 mtspr(SPR_CELL_TSRL, bsp_state[5]);
  318 
  319                 break;
  320         case MPC7450:
  321         case MPC7455:
  322         case MPC7457:
  323                 /* Only MPC745x CPUs have an L3 cache. */
  324                 reg = mpc745x_l3_enable(bsp_state[3]);
  325                 
  326                 /* Fallthrough */
  327         case MPC7400:
  328         case MPC7410:
  329         case MPC7447A:
  330         case MPC7448:
  331                 /* XXX: Program the CPU ID into PIR */
  332                 __asm __volatile("mtspr 1023,%0" :: "r"(PCPU_GET(cpuid)));
  333 
  334                 powerpc_sync();
  335                 isync();
  336 
  337                 mtspr(SPR_HID0, bsp_state[0]); isync();
  338                 mtspr(SPR_HID1, bsp_state[1]); isync();
  339 
  340                 reg = mpc74xx_l2_enable(bsp_state[2]);
  341                 reg = mpc74xx_l1d_enable();
  342                 reg = mpc74xx_l1i_enable();
  343 
  344                 break;
  345         default:
  346 #ifdef __powerpc64__
  347                 if (!(mfmsr() & PSL_HV)) /* Rely on HV to have set things up */
  348                         break;
  349 #endif
  350                 printf("WARNING: Unknown CPU type. Cache performace may be "
  351                     "suboptimal.\n");
  352                 break;
  353         }
  354 }
  355 

Cache object: 960f3919a0c455a60b3969c4c5adbef1


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