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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * General machine architecture & implementation specific 28 * assembly language routines. 29 */ 30 #include "assym.h" 31 32 #include <sys/asm_linkage.h> 33 #include <sys/async.h> 34 #include <sys/machthread.h> 35 #include <sys/vis.h> 36 #include <sys/machsig.h> 37 38 ENTRY(set_trap_table) 39 set trap_table, %o1 40 rdpr %tba, %o0 41 wrpr %o1, %tba 42 retl 43 wrpr %g0, WSTATE_KERN, %wstate 44 SET_SIZE(set_trap_table) 45 46 ! Store long word value at physical address 47 ! 48 ! void stdphys(uint64_t physaddr, uint64_t value) 49 ! 50 ENTRY(stdphys) 51 /* 52 * disable interrupts, clear Address Mask to access 64 bit physaddr 53 */ 54 rdpr %pstate, %o4 55 andn %o4, PSTATE_IE | PSTATE_AM, %o5 56 wrpr %o5, 0, %pstate 57 stxa %o1, [%o0]ASI_MEM 58 retl 59 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 60 SET_SIZE(stdphys) 61 62 63 ! Store long word value at physical i/o address 64 ! 65 ! void stdphysio(u_longlong_t physaddr, u_longlong_t value) 66 ! 67 ENTRY(stdphysio) 68 /* 69 * disable interrupts, clear Address Mask to access 64 bit physaddr 70 */ 71 rdpr %pstate, %o4 72 andn %o4, PSTATE_IE | PSTATE_AM, %o5 73 wrpr %o5, 0, %pstate ! clear IE, AM bits 74 stxa %o1, [%o0]ASI_IO 75 retl 76 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 77 SET_SIZE(stdphysio) 78 79 80 ! 81 ! Load long word value at physical address 82 ! 83 ! uint64_t lddphys(uint64_t physaddr) 84 ! 85 ENTRY(lddphys) 86 rdpr %pstate, %o4 87 andn %o4, PSTATE_IE | PSTATE_AM, %o5 88 wrpr %o5, 0, %pstate 89 ldxa [%o0]ASI_MEM, %o0 90 retl 91 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 92 SET_SIZE(lddphys) 93 94 ! 95 ! Load long word value at physical i/o address 96 ! 97 ! unsigned long long lddphysio(u_longlong_t physaddr) 98 ! 99 ENTRY(lddphysio) 100 rdpr %pstate, %o4 101 andn %o4, PSTATE_IE | PSTATE_AM, %o5 102 wrpr %o5, 0, %pstate ! clear IE, AM bits 103 ldxa [%o0]ASI_IO, %o0 104 retl 105 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 106 SET_SIZE(lddphysio) 107 108 ! 109 ! Store value at physical address 110 ! 111 ! void stphys(uint64_t physaddr, int value) 112 ! 113 ENTRY(stphys) 114 rdpr %pstate, %o4 115 andn %o4, PSTATE_IE | PSTATE_AM, %o5 116 wrpr %o5, 0, %pstate 117 sta %o1, [%o0]ASI_MEM 118 retl 119 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 120 SET_SIZE(stphys) 121 122 123 ! 124 ! load value at physical address 125 ! 126 ! int ldphys(uint64_t physaddr) 127 ! 128 ENTRY(ldphys) 129 rdpr %pstate, %o4 130 andn %o4, PSTATE_IE | PSTATE_AM, %o5 131 wrpr %o5, 0, %pstate 132 lda [%o0]ASI_MEM, %o0 133 srl %o0, 0, %o0 ! clear upper 32 bits 134 retl 135 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 136 SET_SIZE(ldphys) 137 138 ! 139 ! Store value into physical address in I/O space 140 ! 141 ! void stphysio(u_longlong_t physaddr, uint_t value) 142 ! 143 ENTRY_NP(stphysio) 144 rdpr %pstate, %o4 /* read PSTATE reg */ 145 andn %o4, PSTATE_IE | PSTATE_AM, %o5 146 wrpr %o5, 0, %pstate 147 stwa %o1, [%o0]ASI_IO /* store value via bypass ASI */ 148 retl 149 wrpr %g0, %o4, %pstate /* restore the PSTATE */ 150 SET_SIZE(stphysio) 151 152 ! 153 ! Store value into physical address in I/O space 154 ! 155 ! void sthphysio(u_longlong_t physaddr, ushort_t value) 156 ! 157 ENTRY_NP(sthphysio) 158 rdpr %pstate, %o4 /* read PSTATE reg */ 159 andn %o4, PSTATE_IE | PSTATE_AM, %o5 160 wrpr %o5, 0, %pstate 161 stha %o1, [%o0]ASI_IO /* store value via bypass ASI */ 162 retl 163 wrpr %g0, %o4, %pstate /* restore the PSTATE */ 164 SET_SIZE(sthphysio) 165 166 ! 167 ! Store value into one byte physical address in I/O space 168 ! 169 ! void stbphysio(u_longlong_t physaddr, uchar_t value) 170 ! 171 ENTRY_NP(stbphysio) 172 rdpr %pstate, %o4 /* read PSTATE reg */ 173 andn %o4, PSTATE_IE | PSTATE_AM, %o5 174 wrpr %o5, 0, %pstate 175 stba %o1, [%o0]ASI_IO /* store byte via bypass ASI */ 176 retl 177 wrpr %g0, %o4, %pstate /* restore the PSTATE */ 178 SET_SIZE(stbphysio) 179 180 ! 181 ! load value at physical address in I/O space 182 ! 183 ! uint_t ldphysio(u_longlong_t physaddr) 184 ! 185 ENTRY_NP(ldphysio) 186 rdpr %pstate, %o4 /* read PSTATE reg */ 187 andn %o4, PSTATE_IE | PSTATE_AM, %o5 188 wrpr %o5, 0, %pstate 189 lduwa [%o0]ASI_IO, %o0 /* load value via bypass ASI */ 190 retl 191 wrpr %g0, %o4, %pstate /* restore pstate */ 192 SET_SIZE(ldphysio) 193 194 ! 195 ! load value at physical address in I/O space 196 ! 197 ! ushort_t ldhphysio(u_longlong_t physaddr) 198 ! 199 ENTRY_NP(ldhphysio) 200 rdpr %pstate, %o4 /* read PSTATE reg */ 201 andn %o4, PSTATE_IE | PSTATE_AM, %o5 202 wrpr %o5, 0, %pstate 203 lduha [%o0]ASI_IO, %o0 /* load value via bypass ASI */ 204 retl 205 wrpr %g0, %o4, %pstate /* restore pstate */ 206 SET_SIZE(ldhphysio) 207 208 ! 209 ! load byte value at physical address in I/O space 210 ! 211 ! uchar_t ldbphysio(u_longlong_t physaddr) 212 ! 213 ENTRY_NP(ldbphysio) 214 rdpr %pstate, %o4 /* read PSTATE reg */ 215 andn %o4, PSTATE_IE | PSTATE_AM, %o5 216 wrpr %o5, 0, %pstate 217 lduba [%o0]ASI_IO, %o0 /* load value via bypass ASI */ 218 retl 219 wrpr %g0, %o4, %pstate /* restore pstate */ 220 SET_SIZE(ldbphysio) 221 222 /* 223 * save_gsr(kfpu_t *fp) 224 * Store the graphics status register 225 */ 226 227 ENTRY_NP(save_gsr) 228 rd %gsr, %g2 ! save gsr 229 retl 230 stx %g2, [%o0 + FPU_GSR] 231 SET_SIZE(save_gsr) 232 233 ENTRY_NP(restore_gsr) 234 ldx [%o0 + FPU_GSR], %g2 235 wr %g2, %g0, %gsr 236 retl 237 nop 238 SET_SIZE(restore_gsr) 239 240 /* 241 * uint64_t 242 * _fp_read_pgsr() 243 * Get the graphics status register info from fp and return it 244 */ 245 246 ENTRY_NP(_fp_read_pgsr) 247 retl 248 rd %gsr, %o0 249 SET_SIZE(_fp_read_pgsr) 250 251 252 /* 253 * uint64_t 254 * get_gsr(kfpu_t *fp) 255 * Get the graphics status register info from fp and return it 256 */ 257 258 ENTRY_NP(get_gsr) 259 retl 260 ldx [%o0 + FPU_GSR], %o0 261 SET_SIZE(get_gsr) 262 263 /* 264 * _fp_write_pgsr(uint64_t *buf, kfpu_t *fp) 265 * Set the graphics status register info to fp from buf 266 */ 267 268 ENTRY_NP(_fp_write_pgsr) 269 retl 270 mov %o0, %gsr 271 SET_SIZE(_fp_write_pgsr) 272 273 /* 274 * set_gsr(uint64_t buf, kfpu_t *fp) 275 * Set the graphics status register info to fp from buf 276 */ 277 278 ENTRY_NP(set_gsr) 279 retl 280 stx %o0, [%o1 + FPU_GSR] 281 SET_SIZE(set_gsr) 282 283 ENTRY_NP(kdi_cpu_index) 284 CPU_INDEX(%g1, %g2) 285 jmp %g7 286 nop 287 SET_SIZE(kdi_cpu_index) 288 289 ENTRY_NP(kmdb_enter) 290 t ST_KMDB_TRAP 291 retl 292 nop 293 SET_SIZE(kmdb_enter) 294 295 /* 296 * The Spitfire floating point code has been changed not to use install/ 297 * save/restore/fork/freectx() because of the special memcpy library 298 * routines, which will lose too much performance if they have to go 299 * through the fp_disabled trap (which used to call installctx()). So 300 * now fp_save/fp_restore are called from resume, and they don't care 301 * whether floating point was enabled from the user program via the 302 * fp_enabled trap or from the memcpy library, which just turns on floating 303 * point in the fprs register itself. The new routine lwp_freeregs is 304 * called everywhere freectx is called, and code was added to the sun4u- 305 * specific version of lwp_forkregs (which is called everywhere forkctx 306 * is called) to handle forking the floating point registers. 307 * 308 * Note that for the fprs dirty upper/lower bits are not used for now, 309 * because the #instructions to determine if we need to use them is probably 310 * greater than the #insructions just using them. This is a possible future 311 * optimization, only do it with very careful benchmarking! 312 * 313 * The fp_fksave and and fp_load were split into two routines for the 314 * sake of efficiency between the getfpregs/xregs_getfpregs and 315 * setfpregs/xregs_setfpregs. But note that for saving and restoring 316 * context, both *must* happen. For prmachdep, aka access from [k]adb, 317 * it's OK if only one part happens. 318 */ 319 320 /* 321 * fp_save(kfpu_t *fp) 322 * fp_fksave(kfpu_t *fp) 323 * Store the floating point registers. 324 */ 325 326 ENTRY_NP(fp_save) 327 ALTENTRY(fp_fksave) 328 BSTORE_FPREGS(%o0, %o1) ! store V9 regs 329 retl 330 stx %fsr, [%o0 + FPU_FSR] ! store fsr 331 SET_SIZE(fp_fksave) 332 SET_SIZE(fp_save) 333 334 /* 335 * fp_v8_fksave(kfpu_t *fp) 336 * 337 * This is like the above routine but only saves the lower half. 338 */ 339 340 ENTRY_NP(fp_v8_fksave) 341 BSTORE_V8_FPREGS(%o0, %o1) ! store V8 regs 342 retl 343 stx %fsr, [%o0 + FPU_FSR] ! store fsr 344 SET_SIZE(fp_v8_fksave) 345 346 /* 347 * fp_v8p_fksave(kfpu_t *fp) 348 * 349 * This is like the above routine but only saves the upper half. 350 */ 351 352 ENTRY_NP(fp_v8p_fksave) 353 BSTORE_V8P_FPREGS(%o0, %o1) ! store V9 extra regs 354 retl 355 stx %fsr, [%o0 + FPU_FSR] ! store fsr 356 SET_SIZE(fp_v8p_fksave) 357 358 /* 359 * fp_restore(kfpu_t *fp) 360 */ 361 362 ENTRY_NP(fp_restore) 363 BLOAD_FPREGS(%o0, %o1) ! load V9 regs 364 retl 365 ldx [%o0 + FPU_FSR], %fsr ! restore fsr 366 SET_SIZE(fp_restore) 367 368 /* 369 * fp_v8_load(kfpu_t *fp) 370 */ 371 372 ENTRY_NP(fp_v8_load) 373 BLOAD_V8_FPREGS(%o0, %o1) ! load V8 regs 374 retl 375 ldx [%o0 + FPU_FSR], %fsr ! restore fsr 376 SET_SIZE(fp_v8_load) 377 378 /* 379 * fp_v8p_load(kfpu_t *fp) 380 */ 381 382 ENTRY_NP(fp_v8p_load) 383 BLOAD_V8P_FPREGS(%o0, %o1) ! load V9 extra regs 384 retl 385 ldx [%o0 + FPU_FSR], %fsr ! restore fsr 386 SET_SIZE(fp_v8p_load) 387