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 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 /*
  30  * sun4v processor initialization
  31  *
  32  * This is the kernel entry point for CPUs that enter Solaris
  33  * directly from the hypervisor. i.e. without going through OBP.
  34  */
  35 
  36 #if !defined(lint)
  37 #include "assym.h"
  38 #endif /* !lint */
  39 
  40 #include <sys/asm_linkage.h>
  41 #include <sys/hypervisor_api.h>
  42 #include <sys/machasi.h>
  43 #include <sys/machpcb.h>
  44 #include <sys/machlock.h>
  45 #include <sys/mmu.h>
  46 #include <sys/lpad.h>
  47 
  48 #if defined(lint)
  49 
  50 /* ARGSUSED */
  51 void
  52 mach_cpu_startup(uint64_t rabase, uint64_t memsz)
  53 {}
  54 
  55 #else   /* lint */
  56 
  57         /*
  58          * %o0 - hcall specified arg (cpuid)
  59          * %i0 - real memory base
  60          * %i1 - memory size
  61          */
  62         ENTRY_NP(mach_cpu_startup)
  63         /*
  64          * Calculate the data pointer. The landing pad
  65          * data immediately follows the landing pad text.
  66          */
  67         rd      %pc, %l0
  68         add     %l0, LPAD_TEXT_SIZE, %l1        ! %l1 has start of data
  69 
  70         /*
  71          * Setup the initial state of the CPU.
  72          */
  73         wrpr    %g0, 0, %tl
  74         wrpr    %g0, 0, %gl
  75         wrpr    %g0, MAXWIN - 2, %cansave
  76         wrpr    %g0, MAXWIN - 2, %cleanwin
  77         wrpr    %g0, 0, %canrestore
  78         wrpr    %g0, 0, %otherwin
  79         wrpr    %g0, 0, %cwp
  80         wrpr    %g0, 0, %wstate
  81         wr      %g0, %y
  82         wrpr    %g0, PIL_MAX, %pil
  83 
  84         set     trap_table, %g1
  85         wrpr    %g1, %tba
  86 
  87         ! initialize cpuid into scratchpad register
  88         mov     SCRATCHPAD_CPUID, %g1
  89         stxa    %o0, [%g1]ASI_SCRATCHPAD
  90         
  91         ! sanity check the data section
  92         setx    LPAD_MAGIC_VAL, %g2, %g1
  93         ldx     [%l1 + LPAD_MAGIC], %g2
  94         cmp     %g1, %g2
  95         bne     startup_error
  96           nop
  97 
  98         /*
  99          * Loop through the array of TTE's, installing the
 100          * VA to RA mapping for each one.
 101          */
 102         ldx     [%l1 + LPAD_NMAP], %l2          ! %l2 = number of mappings
 103         add     %l1, LPAD_MAP, %l3              ! %l3 = the current mapping
 104 
 105         /*
 106          * Sanity check the number of mappings.
 107          */
 108         mulx    %l2, LPAD_MAP_SIZE, %g1
 109         add     %l3, %g1, %g1                   ! %g1 = end of the array
 110         add     %l1, LPAD_DATA_SIZE, %g2        ! %g2 = end of data section
 111         sub     %g2, %g1, %g2
 112         brlz    %g2, startup_error
 113           nop
 114 
 115 0:
 116         cmp     %l2, %g0
 117         be      3f
 118           nop
 119 
 120         ldx     [%l3 + LPAD_MAP_FLAGS], %l4     ! %l4 = flags
 121 
 122         /*
 123          * Generate args for the HV call
 124          */
 125         ldx     [%l3 + LPAD_MAP_VA], %o0        ! %o0 = virtual address
 126         mov     KCONTEXT, %o1                   ! %o1 = context
 127         ldx     [%l3 + LPAD_MAP_TTE], %o2       ! %o2 = TTE
 128         and     %l4, FLAG_MMUFLAGS_MASK, %o3    ! %o3 = MMU flags
 129 
 130         ! check if this is a locked TTE
 131         and     %l4, FLAG_LOCK_MASK, %l4
 132         cmp     %l4, %g0
 133         bne     1f
 134           nop
 135 
 136         ! install an unlocked entry
 137         ta      MMU_MAP_ADDR
 138         ba      2f
 139           nop
 140 1:
 141         ! install a locked entry
 142         mov     MAP_PERM_ADDR, %o5
 143         ta      FAST_TRAP
 144 
 145 2:
 146         ! check for errors from the hcall
 147         cmp     %o0, %g0
 148         bne     startup_error
 149           nop
 150         
 151         sub     %l2, 1, %l2                     ! decrement counter
 152         add     %l3, LPAD_MAP_SIZE, %l3         ! increment pointer
 153 
 154         ba      0b
 155           nop
 156 
 157 3:
 158         /*
 159          * Set the MMU fault status area
 160          */
 161         ldx     [%l1 + LPAD_MMFSA_RA], %o0
 162 
 163         mov     MMU_SET_INFOPTR, %o5
 164         ta      FAST_TRAP
 165 
 166         ! check for errors from the hcall
 167         cmp     %o0, %g0
 168         bne     startup_error
 169           nop
 170 
 171         /*
 172          * Load remaining arguments before enabling the
 173          * MMU so that the loads can be done using real
 174          * addresses.
 175          */
 176         ldx     [%l1 + LPAD_PC], %l3            ! %l3 = specified entry point
 177         ldx     [%l1 + LPAD_ARG], %l4           ! %l4 = specified argument
 178         ldx     [%l1 + LPAD_INUSE], %l5         ! %l5 = va of inuse mailbox
 179 
 180         /*
 181          * Enable the MMU. On success, it returns to the
 182          * global version of the landing pad text, rather
 183          * than the text copied into the lpad buffer.
 184          */
 185         mov     1, %o0                          ! %o0 = enable flag (1 = enable)
 186         set     startup_complete, %o1           ! VA of return address
 187         mov     MMU_ENABLE, %o5
 188         ta      FAST_TRAP
 189 
 190         /*
 191          * On errors, just enter a spin loop until the
 192          * CPU that initiated the start recovers the CPU.
 193          */
 194 startup_error:
 195         ba      startup_error
 196           nop
 197 
 198         /*
 199          * Jump to the generic CPU initialization code.
 200          */
 201 startup_complete:
 202         mov     %l4, %o0
 203         jmpl    %l3, %g0
 204           stx   %g0, [%l5]                      ! clear the inuse mailbox
 205 
 206         SET_SIZE(mach_cpu_startup)
 207 
 208         .global mach_cpu_startup_end
 209 mach_cpu_startup_end:
 210 
 211 #endif  /* lint */