1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #if defined(lint)
  27 #include <sys/types.h>
  28 #else   /* lint */
  29 #include "assym.h"
  30 #endif  /* lint */
  31 
  32 #include <sys/asm_linkage.h>
  33 #include <sys/machthread.h>
  34 #include <sys/param.h>
  35 #include <sys/vm_machparam.h>
  36 #include <sys/privregs.h>
  37 #include <sys/intreg.h>
  38 #include <sys/vis.h>
  39 #include <sys/clock.h>
  40 #include <vm/hat_sfmmu.h> 
  41 
  42 #if !defined(lint)
  43         .weak   cpu_feature_init
  44         .type   cpu_feature_init, #function
  45 #endif  /* lint */
  46 
  47 #if !defined(lint)
  48         .weak   cpu_early_feature_init
  49         .type   cpu_early_feature_init, #function
  50 #endif  /* lint */
  51 
  52 /*
  53  * Processor initialization
  54  *
  55  * This is the kernel entry point for other cpus except the first one.
  56  * When the prom jumps to this location we are still executing with the
  57  * prom's trap table.  It expects the cpuid as its first parameter.
  58  */
  59 
  60 #if defined(lint)
  61 
  62 /* ARGSUSED */
  63 void
  64 cpu_startup(int cpuid)
  65 {}
  66 
  67 #else   /* lint */
  68 
  69         ! allocate a temporary stack to run on while we figure who and
  70         ! what we are.
  71         .seg    ".data"
  72         .align  8
  73 etmpstk:
  74         .skip   2048
  75 tmpstk:
  76         .word   0
  77 
  78         ENTRY_NP(cpu_startup)
  79         !
  80         ! Initialize CPU state registers
  81         !
  82         ! The boot cpu and other cpus are different.  The boot cpu has gone
  83         ! through boot, and its state might be affected as a result.  The
  84         ! other cpus' states come directly from the prom.
  85         !
  86         wrpr    %g0, PSTATE_KERN, %pstate
  87         wr      %g0, %g0, %fprs         ! clear fprs
  88         CLEARTICKNPT                    ! allow user rdtick
  89 
  90         !
  91         ! Set up temporary stack
  92         !
  93         set     tmpstk, %g1
  94         sub     %g1, SA(KFPUSIZE+GSR_SIZE), %g2
  95         and     %g2, 0x3F, %g3
  96         sub     %g2, %g3, %o2
  97         sub     %o2, SA(MINFRAME) + STACK_BIAS, %sp
  98 
  99         mov     %o0, %l1                ! save cpuid
 100 
 101         call    sfmmu_mp_startup
 102         sub     %g0, 1, THREAD_REG      ! catch any curthread acceses
 103         
 104         ! On OPL platforms, context page size TLB programming must be enabled in
 105         ! ASI_MEMCNTL.  To avoid Olympus-C and Jupiter sTLB errata (strands with
 106         ! different TLB page size settings), this must be done here before any
 107         ! reference to non-nucleus memory.  An early hook is added to perform
 108         ! cpu specific initialization.
 109         !
 110         sethi   %hi(cpu_early_feature_init), %o0
 111         or      %o0, %lo(cpu_early_feature_init), %o0
 112         brz     %o0, 0f
 113         nop
 114         call    %o0
 115         nop
 116 
 117 0:
 118         ! SET_KCONTEXTREG(reg0, reg1, reg2, reg3, reg4, label1, label2, label3)
 119         SET_KCONTEXTREG(%o0, %g1, %g2, %g3, %l3, l1, l2, l3)
 120         
 121         ! We are now running on the kernel's trap table.
 122         ! 
 123         ! It is very important to have a thread pointer and a cpu struct
 124         ! *before* calling into C routines .
 125         ! Otherwise, overflow/underflow handlers, etc. can get very upset!
 126         ! 
 127         !
 128         ! We don't want to simply increment
 129         ! ncpus right now because it is in the cache, and
 130         ! we don't have the cache on yet for this CPU.
 131         !
 132         set     cpu, %l3
 133         sll     %l1, CPTRSHIFT, %l2     ! offset into CPU vector.
 134         ldn     [%l3 + %l2], %l3        ! pointer to CPU struct
 135         ldn     [%l3 + CPU_THREAD], THREAD_REG  ! set thread pointer (%g7)
 136 
 137         !
 138         ! Set up any required cpu feature
 139         !
 140         sethi   %hi(cpu_feature_init), %o0
 141         or      %o0, %lo(cpu_feature_init), %o0
 142         brz     %o0, 1f
 143         nop
 144         call    %o0
 145         nop
 146 
 147 1:
 148         !
 149         ! Resume the thread allocated for the CPU.
 150         !
 151         ldn     [THREAD_REG + T_PC], %i7
 152         ldn     [THREAD_REG + T_SP], %fp
 153         ret                             ! "return" into the thread
 154         restore                         ! WILL cause underflow
 155         SET_SIZE(cpu_startup)
 156 
 157 #endif  /* lint */