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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#include "assym.h" 28 29#include <sys/asm_linkage.h> 30#include <sys/machthread.h> /* for reg definition */ 31 32#include <sys/machasi.h> /* sun4u ASI */ 33#include <sys/mmu.h> 34#include <sys/privregs.h> 35#include <sys/machparam.h> 36#include <vm/hat_sfmmu.h> 37#include <sys/cpr_impl.h> 38#include <sys/intreg.h> 39#include <sys/clock.h> 40 41/* 42 * resume kernel entry point from cprboot 43 * 1. restore I/D TSB registers 44 * 2. restore primary and secondary context registers 45 * 3. initialize cpu state registers 46 * 4. set up the thread and lwp registers for the cpr process 47 * 5. switch to kernel trap 48 * 6. restore checkpoint pc and stack pointer 49 * 7. longjmp back to kernel 50 * 51 * registers from cprboot:exit_to_kernel() 52 * %o0 prom cookie 53 * %o1 struct sun4u_machdep *mdp 54 * 55 * Any change to this register assignment 56 * require changes to cprboot_srt0.s 57 */ 58 59 ! 60 ! reserve 4k for cpr tmp stack; tstack should be first, 61 ! any new data symbols should be added after tstack. 62 ! 63 .seg ".data" 64 .global i_cpr_data_page, i_cpr_tstack_size 65 .global i_cpr_orig_cif 66 67 .align MMU_PAGESIZE 68i_cpr_data_page: 69 .skip 4096 70i_cpr_tstack: 71 .word 0 72i_cpr_tstack_size: 73 .word 4096 74 75 .align 8 76prom_tba: 77 .word 0, 0 78i_cpr_orig_cif: 79 .nword 0 80i_cpr_tmp_cif: 81 .nword 0 82 83 84 ! 85 ! set text to begin at a page boundary so we can 86 ! map this one page and jump to it from cprboot 87 ! 88 .seg ".text" 89 .align MMU_PAGESIZE 90 91 ENTRY(i_cpr_resume_setup) 92 ! 93 ! save %o args to locals 94 ! 95 mov %o0, %l4 96 mov %o1, %l5 97 98 ! 99 ! Restore PCONTEXT 100 ! 101 sethi %hi(FLUSH_ADDR), %g3 102 ld [%l5 + CPR_MD_PRI], %g1 ! mdp->mmu_ctx_pri 103 set MMU_PCONTEXT, %g2 104 stxa %g1, [%g2]ASI_DMMU 105 flush %g3 106 107 ! 108 ! Restore SCONTEXT. We do not need to set up the TSB 109 ! registers. Since we are restoring INVALID_CONTEXT into 110 ! the secondary context the HAT will do that for us. 111 ! 112 ld [%l5 + CPR_MD_SEC], %g1 ! mdp->mmu_ctx_sec 113 set MMU_SCONTEXT, %g2 114 stxa %g1, [%g2]ASI_DMMU 115 flush %g3 116 117 ! 118 ! Allow user rdtick, and rdstick if applicable 119 ! 120 CLEARTICKNPT 121 122 ! 123 ! copy saved thread pointer to %g7 124 ! 125 ldx [%l5 + CPR_MD_THRP], THREAD_REG ! mdp->thrp 126 127 ! 128 ! since csu_md_t lives in a cprboot data page, 129 ! copy select data to registers for later use 130 ! before freeing cprboot text/data pages 131 ! 132 ldx [%l5 + CPR_MD_QSAV_PC], %l7 ! l7 = mdp->qsav_pc 133 ldx [%l5 + CPR_MD_QSAV_SP], %l6 ! l6 = mdp->qsav_sp 134 135 ! 136 ! save cookie from the new/tmp prom 137 ! 138 set i_cpr_tmp_cif, %g1 139 stn %l4, [%g1] 140 141 ! 142 ! save prom tba 143 ! 144 set prom_tba, %g1 145 rdpr %tba, %g2 146 stx %g2, [%g1] 147 148 ! 149 ! start slave cpus, pause them within kernel text, 150 ! and restore the original prom pages 151 ! 152 call i_cpr_mp_setup 153 nop 154 155 ! 156 ! since this routine is entered only by a jmp from cprboot, 157 ! we can set cpr_suspend_succeeded here 158 ! 159 set cpr_suspend_succeeded, %l0 160 mov 1, %l1 161 st %l1, [%l0] 162 163 ! 164 ! special shortened version of longjmp 165 ! Don't need to flushw 166 ! 167 mov %l7, %i7 ! i7 = saved pc 168 mov %l6, %fp ! i6 = saved sp 169 ret ! return 1 170 restore %g0, 1, %o0 ! takes underflow, switches stack 171 SET_SIZE(i_cpr_resume_setup) 172 173 174 ! 175 ! while running on the new/tmp prom, the prom's trap table 176 ! must be used to handle translations within prom space 177 ! since the kernel's mappings may not match this prom. 178 ! 179 ! always set %tba to the prom's trap table before calling 180 ! any prom service; after returning, read %tba again; 181 ! if the %tba wasn't changed by the prom service, 182 ! restore the original %tba. 183 ! 184 ! a call stack looks like this: 185 ! 186 ! current prom cookie 187 ! [i_cpr_cif_wrapper] 188 ! client_handler 189 ! p1275_sparc_cif_handler 190 ! prom_xxx 191 ! 192 ENTRY(i_cpr_cif_wrapper) 193 save %sp, -SA64(MINFRAME64 + 8), %sp 194 rdpr %tba, %o5 ! read original %tba 195 stx %o5, [%fp + V9BIAS64 - 8] 196 set prom_tba, %l4 197 ldx [%l4], %o4 ! read prom_tba 198 wrpr %o4, %tba ! switch to prom trap table 199 200 set i_cpr_tmp_cif, %g3 ! cookie for new/tmp prom 201 ldn [%g3], %g4 202 jmpl %g4, %o7 ! call prom service 203 mov %i0, %o0 204 205 ldx [%l4], %o4 ! read prom_tba 206 rdpr %tba, %o3 ! read current %tba 207 cmp %o3, %o4 ! did prom change %tba ? 208 bne,pn %xcc, 1f ! yes, dont reset %tba 209 nop 210 ldx [%fp + V9BIAS64 - 8], %o5 211 wrpr %o5, %tba ! no change, restore orignal 2121: 213 ret 214 restore %g0, %o0, %o0 215 SET_SIZE(i_cpr_cif_wrapper) 216 217 218 ! 219 ! write dtlb entry at index 220 ! 221 ENTRY(dtlb_wr_entry) 222 sllx %o0, 3, %o0 ! index << 3 223 ldx [%o1], %o5 ! o5 = tte.ll 224 ldx [%o2], %o4 ! o4 = va_tag 225 srlx %o4, MMU_PAGESHIFT, %o4 ! clear any page offset 226 sllx %o4, MMU_PAGESHIFT, %o4 ! o4 = va_tag & PAGEMASK 227 set MMU_TAG_ACCESS, %o3 228 stxa %o4, [%o3]ASI_DMMU 229 stxa %o5, [%o0]ASI_DTLB_ACCESS 230 membar #Sync 231 retl 232 nop 233 SET_SIZE(dtlb_wr_entry) 234 235 236 ! 237 ! write itlb entry at index 238 ! 239 ENTRY(itlb_wr_entry) 240 sllx %o0, 3, %o0 ! index << 3 241 ldx [%o1], %o5 ! o5 = tte.ll 242 ldx [%o2], %o4 ! o4 = va_tag 243 srlx %o4, MMU_PAGESHIFT, %o4 ! clear any page offset 244 sllx %o4, MMU_PAGESHIFT, %o4 ! o4 = va_tag & PAGEMASK 245 set MMU_TAG_ACCESS, %o3 246 stxa %o4, [%o3]ASI_IMMU 247 stxa %o5, [%o0]ASI_ITLB_ACCESS 248 membar #Sync 249 retl 250 nop 251 SET_SIZE(itlb_wr_entry) 252 253