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