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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28#if defined(lint) 29#include <sys/types.h> 30#include <sys/thread.h> 31#else /* lint */ 32#include "assym.h" 33#endif /* lint */ 34 35#include <sys/asm_linkage.h> 36#include <sys/machthread.h> 37#include <sys/machcpuvar.h> 38#include <sys/intreg.h> 39#include <sys/cmn_err.h> 40#include <sys/ftrace.h> 41#include <sys/machasi.h> 42#include <sys/scb.h> 43#include <sys/error.h> 44#define INTR_REPORT_SIZE 64 45 46#ifdef TRAPTRACE 47#include <sys/traptrace.h> 48#endif /* TRAPTRACE */ 49 50#if defined(lint) 51 52void 53cpu_mondo(void) 54{} 55 56#else /* lint */ 57 58 59/* 60 * (TT 0x7c, TL>0) CPU Mondo Queue Handler 61 * Globals are the Interrupt Globals. 62 */ 63 ENTRY_NP(cpu_mondo) 64 ! 65 ! Register Usage:- 66 ! %g5 PC for fasttrap TL>0 handler 67 ! %g1 arg 1 68 ! %g2 arg 2 69 ! %g3 queue base VA 70 ! %g4 queue size mask 71 ! %g6 head ptr 72 ! %g7 tail ptr 73 mov CPU_MONDO_Q_HD, %g3 74 ldxa [%g3]ASI_QUEUE, %g6 ! %g6 = head ptr 75 mov CPU_MONDO_Q_TL, %g4 76 ldxa [%g4]ASI_QUEUE, %g7 ! %g7 = tail ptr 77 cmp %g6, %g7 78 be,pn %xcc, 0f ! head == tail 79 nop 80 81 CPU_ADDR(%g1,%g2) 82 add %g1, CPU_MCPU, %g2 83 ldx [%g2 + MCPU_CPU_Q_BASE], %g3 ! %g3 = queue base PA 84 ldx [%g2 + MCPU_CPU_Q_SIZE], %g4 ! queue size 85 sub %g4, 1, %g4 ! %g4 = queue size mask 86 87 ! Load interrupt receive data registers 1 and 2 to fetch 88 ! the arguments for the fast trap handler. 89 ! 90 ! XXX - Since the data words in the interrupt report are not defined yet 91 ! we assume that the consective words contain valid data and preserve 92 ! sun4u's xcall mondo arguments. 93 ! Register usage: 94 ! %g5 PC for fasttrap TL>0 handler 95 ! %g1 arg 1 96 ! %g2 arg 2 97 98 ldxa [%g3 + %g6]ASI_MEM, %g5 ! get PC from q base + head 99 add %g6, 0x8, %g6 ! inc head 100 ldxa [%g3 + %g6]ASI_MEM, %g1 ! read data word 1 101 add %g6, 0x8, %g6 ! inc head 102 ldxa [%g3 + %g6]ASI_MEM, %g2 ! read data word 2 103 add %g6, (INTR_REPORT_SIZE - 16) , %g6 ! inc head to next record 104 and %g6, %g4, %g6 ! and size mask for wrap around 105 mov CPU_MONDO_Q_HD, %g3 106 stxa %g6, [%g3]ASI_QUEUE ! store head pointer 107 membar #Sync 108 109#ifdef TRAPTRACE 110 TRACE_PTR(%g4, %g6) 111 GET_TRACE_TICK(%g6) 112 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 113 TRACE_SAVE_TL_GL_REGS(%g4, %g6) 114 rdpr %tt, %g6 115 stha %g6, [%g4 + TRAP_ENT_TT]%asi 116 rdpr %tpc, %g6 117 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 118 rdpr %tstate, %g6 119 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 120 stna %sp, [%g4 + TRAP_ENT_SP]%asi 121 stna %g5, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 122 stna %g1, [%g4 + TRAP_ENT_F1]%asi ! arg1 123 stna %g2, [%g4 + TRAP_ENT_F3]%asi ! arg2 124 mov CPU_MONDO_Q_HD, %g6 125 ldxa [%g6]ASI_QUEUE, %g6 ! new head offset 126 stna %g6, [%g4 + TRAP_ENT_F2]%asi 127 stna %g7, [%g4 + TRAP_ENT_F4]%asi ! tail offset 128 TRACE_NEXT(%g4, %g6, %g3) 129#endif /* TRAPTRACE */ 130 131 /* 132 * For now catch invalid PC being passed via cpu_mondo queue 133 */ 134 set KERNELBASE, %g4 135 cmp %g5, %g4 136 bl,a,pn %xcc, 1f ! branch if bad %pc 137 nop 138 139 jmp %g5 ! jump to traphandler 140 nop 1411: 142 ! invalid trap handler, discard it for now 143 set cpu_mondo_inval, %g4 144 ldx [%g4], %g5 145 inc %g5 146 stx %g5, [%g4] 1470: 148 retry 149 /* Never Reached */ 150 SET_SIZE(cpu_mondo) 151 152#endif /* lint */ 153 154#if defined(lint) 155 156void 157dev_mondo(void) 158{} 159 160#else /* lint */ 161 162 163/* 164 * (TT 0x7d, TL>0) Dev Mondo Queue Handler 165 * Globals are the Interrupt Globals. 166 * We only process one interrupt at a time causing us to keep 167 * taking this trap till the queue is empty. 168 * We really should drain the whole queue for better performance 169 * but this will do for now. 170 */ 171 ENTRY_NP(dev_mondo) 172 ! 173 ! Register Usage:- 174 ! %g5 PC for fasttrap TL>0 handler 175 ! %g1 arg 1 176 ! %g2 arg 2 177 ! %g3 queue base PA 178 ! %g4 queue size mask 179 ! %g6 head ptr 180 ! %g7 tail ptr 181 mov DEV_MONDO_Q_HD, %g3 182 ldxa [%g3]ASI_QUEUE, %g6 ! %g6 = head ptr 183 mov DEV_MONDO_Q_TL, %g4 184 ldxa [%g4]ASI_QUEUE, %g7 ! %g7 = tail ptr 185 cmp %g6, %g7 186 be,pn %xcc, 0f ! head == tail 187 nop 188 189 CPU_ADDR(%g1,%g2) 190 add %g1, CPU_MCPU, %g2 191 ldx [%g2 + MCPU_DEV_Q_BASE], %g3 ! %g3 = queue base PA 192 193 ! Register usage: 194 ! %g5 - inum 195 ! %g1 - cpu struct pointer used below in TRAPTRACE 196 ! 197 ldxa [%g3 + %g6]ASI_MEM, %g5 ! get inum from q base + head 198 199 ! 200 ! We verify that inum is valid ( < MAXVNUM). If it is greater 201 ! than MAXVNUM, we let setvecint_tl1 take care of it. 202 ! 203 set MAXIVNUM, %g4 204 cmp %g5, %g4 205 bgeu,a,pn %xcc, 1f 206 ldx [%g2 + MCPU_DEV_Q_SIZE], %g4 ! queue size - delay slot 207 208 ! 209 ! Copy 64-byte payload to the *iv_payload if it is not NULL 210 ! 211 set intr_vec_table, %g1 ! %g1 = intr_vec_table 212 sll %g5, CPTRSHIFT, %g7 ! %g7 = offset to inum entry 213 ! in the intr_vec_table 214 add %g1, %g7, %g7 ! %g7 = &intr_vec_table[inum] 215 ldn [%g7], %g1 ! %g1 = ptr to intr_vec_t (iv) 216 ldx [%g1 + IV_PAYLOAD_BUF], %g1 ! %g1 = iv->iv_payload_buf 217 brz,a,pt %g1, 1f ! if it is NULL 218 ldx [%g2 + MCPU_DEV_Q_SIZE], %g4 ! queue size - delay slot 219 220 ! 221 ! Now move 64 byte payload from mondo queue to buf 222 ! 223 mov %g6, %g7 ! %g7 = head ptr 224 ldxa [%g3 + %g7]ASI_MEM, %g4 225 stx %g4, [%g1 + 0] ! byte 0 - 7 226 add %g7, 8, %g7 227 ldxa [%g3 + %g7]ASI_MEM, %g4 228 stx %g4, [%g1 + 8] ! byte 8 - 15 229 add %g7, 8, %g7 230 ldxa [%g3 + %g7]ASI_MEM, %g4 231 stx %g4, [%g1 + 16] ! byte 16 - 23 232 add %g7, 8, %g7 233 ldxa [%g3 + %g7]ASI_MEM, %g4 234 stx %g4, [%g1 + 24] ! byte 24 - 31 235 add %g7, 8, %g7 236 ldxa [%g3 + %g7]ASI_MEM, %g4 237 stx %g4, [%g1 + 32] ! byte 32 - 39 238 add %g7, 8, %g7 239 ldxa [%g3 + %g7]ASI_MEM, %g4 240 stx %g4, [%g1 + 40] ! byte 40 - 47 241 add %g7, 8, %g7 242 ldxa [%g3 + %g7]ASI_MEM, %g4 243 stx %g4, [%g1 + 48] ! byte 48 - 55 244 add %g7, 8, %g7 245 ldxa [%g3 + %g7]ASI_MEM, %g4 246 stx %g4, [%g1 + 56] ! byte 56 - 63 247 ldx [%g2 + MCPU_DEV_Q_SIZE], %g4 ! queue size 248 2491: sub %g4, 1, %g4 ! %g4 = queue size mask 250 add %g6, INTR_REPORT_SIZE , %g6 ! inc head to next record 251 and %g6, %g4, %g6 ! and mask for wrap around 252 mov DEV_MONDO_Q_HD, %g3 253 stxa %g6, [%g3]ASI_QUEUE ! increment head offset 254 membar #Sync 255 256#ifdef TRAPTRACE 257 TRACE_PTR(%g4, %g6) 258 GET_TRACE_TICK(%g6) 259 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 260 TRACE_SAVE_TL_GL_REGS(%g4, %g6) 261 rdpr %tt, %g6 262 stha %g6, [%g4 + TRAP_ENT_TT]%asi 263 rdpr %tpc, %g6 264 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 265 rdpr %tstate, %g6 266 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 267 ! move head to sp 268 ldx [%g2 + MCPU_DEV_Q_BASE], %g6 269 stna %g6, [%g4 + TRAP_ENT_SP]%asi ! Device Queue Base PA 270 stna %g5, [%g4 + TRAP_ENT_TR]%asi ! Inum 271 mov DEV_MONDO_Q_HD, %g6 272 ldxa [%g6]ASI_QUEUE, %g6 ! New head offset 273 stna %g6, [%g4 + TRAP_ENT_F1]%asi 274#ifdef __sparcv9 275 ldx [%g2 + MCPU_DEV_Q_SIZE], %g6 276 stna %g6, [%g4 + TRAP_ENT_F2]%asi ! Q Size 277 stna %g7, [%g4 + TRAP_ENT_F3]%asi ! tail offset 278 stna %g0, [%g4 + TRAP_ENT_F4]%asi 279#endif 280 TRACE_NEXT(%g4, %g6, %g3) 281#endif /* TRAPTRACE */ 282 283 ! 284 ! setvecint_tl1 will do all the work, and finish with a retry 285 ! 286 ba,pt %xcc, setvecint_tl1 287 mov %g5, %g1 ! setvecint_tl1 expects inum in %g1 288 2890: retry 290 291 /* Never Reached */ 292 SET_SIZE(dev_mondo) 293#endif /* lint */ 294 295#if defined(lint) 296uint64_t cpu_mondo_inval; 297#else /* lint */ 298 .seg ".data" 299 .global cpu_mondo_inval 300 .align 8 301cpu_mondo_inval: 302 .skip 8 303 304 .seg ".text" 305#endif /* lint */ 306 307 308#if defined(lint) 309 310void 311resumable_error(void) 312{} 313 314#else /* lint */ 315 316/* 317 * (TT 0x7e, TL>0) Resumeable Error Queue Handler 318 * We keep a shadow copy of the queue in kernel buf. 319 * Read the resumable queue head and tail offset 320 * If there are entries on the queue, move them to 321 * the kernel buf, which is next to the resumable 322 * queue in the memory. Call C routine to process. 323 */ 324 ENTRY_NP(resumable_error) 325 mov CPU_RQ_HD, %g4 326 ldxa [%g4]ASI_QUEUE, %g2 ! %g2 = Q head offset 327 mov CPU_RQ_TL, %g4 328 ldxa [%g4]ASI_QUEUE, %g3 ! %g3 = Q tail offset 329 mov %g2, %g6 ! save head in %g2 330 331 cmp %g6, %g3 332 be,pn %xcc, 0f ! head == tail 333 nop 334 335 CPU_ADDR(%g1, %g4) ! %g1 = cpu struct addr 336 3372: set CPU_RQ_BASE_OFF, %g4 338 ldx [%g1 + %g4], %g4 ! %g4 = queue base PA 339 add %g6, %g4, %g4 ! %g4 = PA of ER in Q 340 set CPU_RQ_SIZE, %g7 341 add %g4, %g7, %g7 ! %g7=PA of ER in kernel buf 342 343 ldxa [%g7]ASI_MEM, %g5 ! %g5=first 8 byte of ER buf 344 cmp 0, %g5 345 bne,pn %xcc, 1f ! first 8 byte is not 0 346 nop 347 348 /* Now we can move 64 bytes from queue to buf */ 349 set 0, %g5 350 ldxa [%g4 + %g5]ASI_MEM, %g1 351 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 0 - 7 352 add %g5, 8, %g5 353 ldxa [%g4 + %g5]ASI_MEM, %g1 354 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 8 - 15 355 add %g5, 8, %g5 356 ldxa [%g4 + %g5]ASI_MEM, %g1 357 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 16 - 23 358 add %g5, 8, %g5 359 ldxa [%g4 + %g5]ASI_MEM, %g1 360 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 24 - 31 361 add %g5, 8, %g5 362 ldxa [%g4 + %g5]ASI_MEM, %g1 363 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 32 - 39 364 add %g5, 8, %g5 365 ldxa [%g4 + %g5]ASI_MEM, %g1 366 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 40 - 47 367 add %g5, 8, %g5 368 ldxa [%g4 + %g5]ASI_MEM, %g1 369 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 48 - 55 370 add %g5, 8, %g5 371 ldxa [%g4 + %g5]ASI_MEM, %g1 372 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 56 - 63 373 374 set CPU_RQ_SIZE, %g5 ! %g5 = queue size 375 sub %g5, 1, %g5 ! %g5 = queu size mask 376 377 add %g6, Q_ENTRY_SIZE, %g6 ! increment q head to next 378 and %g6, %g5, %g6 ! size mask for warp around 379 cmp %g6, %g3 ! head == tail ?? 380 381 bne,pn %xcc, 2b ! still have more to process 382 nop 383 384 /* 385 * head equals to tail now, we can update the queue head 386 * and call sys_trap 387 */ 388 mov CPU_RQ_HD, %g4 389 stxa %g6, [%g4]ASI_QUEUE ! update head offset 390 391 /* 392 * Call sys_trap at PIL 14 unless we're already at PIL 15. %g2.l is 393 * head offset(arg2) and %g3 is tail 394 * offset(arg3). 395 */ 396 set process_resumable_error, %g1 397 rdpr %pil, %g4 398 cmp %g4, PIL_14 399 ba sys_trap 400 movl %icc, PIL_14, %g4 401 402 /* 403 * We are here because the C routine is not able to process 404 * errors in time. So the first 8 bytes of ER in buf has not 405 * been cleared. We update head to tail and call sys_trap to 406 * print out an error message 407 */ 408 4091: mov CPU_RQ_HD, %g4 410 stxa %g3, [%g4]ASI_QUEUE ! set head equal to tail 411 412 /* 413 * Set %g2 to %g6, which is current head offset. %g2 414 * is arg2 of the C routine. %g3 is the tail offset, 415 * which is arg3 of the C routine. 416 * Call rq_overflow at PIL 14 unless we're already at PIL 15. 417 */ 418 mov %g6, %g2 419 set rq_overflow, %g1 420 rdpr %pil, %g4 421 cmp %g4, PIL_14 422 ba sys_trap 423 movl %icc, PIL_14, %g4 424 4250: retry 426 427 /*NOTREACHED*/ 428 SET_SIZE(resumable_error) 429#endif /* lint */ 430 431#if defined(lint) 432 433void 434nonresumable_error(void) 435{} 436 437#else /* lint */ 438 439/* 440 * (TT 0x7f, TL>0) Non-resumeable Error Queue Handler 441 * We keep a shadow copy of the queue in kernel buf. 442 * Read non-resumable queue head and tail offset 443 * If there are entries on the queue, move them to 444 * the kernel buf, which is next to the non-resumable 445 * queue in the memory. Call C routine to process. 446 */ 447 ENTRY_NP(nonresumable_error) 448 mov CPU_NRQ_HD, %g4 449 ldxa [%g4]ASI_QUEUE, %g2 ! %g2 = Q head offset 450 mov CPU_NRQ_TL, %g4 451 ldxa [%g4]ASI_QUEUE, %g3 ! %g3 = Q tail offset 452 453 cmp %g2, %g3 454 be,pn %xcc, 0f ! head == tail 455 nop 456 457 /* force %gl to 1 as sys_trap requires */ 458 wrpr %g0, 1, %gl 459 mov CPU_NRQ_HD, %g4 460 ldxa [%g4]ASI_QUEUE, %g2 ! %g2 = Q head offset 461 mov CPU_NRQ_TL, %g4 462 ldxa [%g4]ASI_QUEUE, %g3 ! %g3 = Q tail offset 463 mov %g2, %g6 ! save head in %g2 464 465 CPU_PADDR(%g1, %g4) ! %g1 = cpu struct paddr 466 4672: set CPU_NRQ_BASE_OFF, %g4 468 ldxa [%g1 + %g4]ASI_MEM, %g4 ! %g4 = queue base PA 469 add %g6, %g4, %g4 ! %g4 = PA of ER in Q 470 set CPU_NRQ_SIZE, %g7 471 add %g4, %g7, %g7 ! %g7 = PA of ER in kernel buf 472 473 ldxa [%g7]ASI_MEM, %g5 ! %g5 = first 8 byte of ER buf 474 cmp 0, %g5 475 bne,pn %xcc, 1f ! first 8 byte is not 0 476 nop 477 478 /* Now we can move 64 bytes from queue to buf */ 479 set 0, %g5 480 ldxa [%g4 + %g5]ASI_MEM, %g1 481 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 0 - 7 482 add %g5, 8, %g5 483 ldxa [%g4 + %g5]ASI_MEM, %g1 484 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 8 - 15 485 add %g5, 8, %g5 486 ldxa [%g4 + %g5]ASI_MEM, %g1 487 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 16 - 23 488 add %g5, 8, %g5 489 ldxa [%g4 + %g5]ASI_MEM, %g1 490 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 24 - 31 491 add %g5, 8, %g5 492 ldxa [%g4 + %g5]ASI_MEM, %g1 493 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 32 - 39 494 add %g5, 8, %g5 495 ldxa [%g4 + %g5]ASI_MEM, %g1 496 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 40 - 47 497 add %g5, 8, %g5 498 ldxa [%g4 + %g5]ASI_MEM, %g1 499 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 48 - 55 500 add %g5, 8, %g5 501 ldxa [%g4 + %g5]ASI_MEM, %g1 502 stxa %g1, [%g7 + %g5]ASI_MEM ! byte 56 - 63 503 504 set CPU_NRQ_SIZE, %g5 ! %g5 = queue size 505 sub %g5, 1, %g5 ! %g5 = queu size mask 506 507 add %g6, Q_ENTRY_SIZE, %g6 ! increment q head to next 508 and %g6, %g5, %g6 ! size mask for warp around 509 cmp %g6, %g3 ! head == tail ?? 510 511 bne,pn %xcc, 2b ! still have more to process 512 nop 513 514 /* 515 * head equals to tail now, we can update the queue head 516 * and call sys_trap 517 */ 518 mov CPU_NRQ_HD, %g4 519 stxa %g6, [%g4]ASI_QUEUE ! update head offset 520 521 /* 522 * Call sys_trap. %g2 is TL(arg2), %g3 is head and tail 523 * offset(arg3). 524 * %g3 looks like following: 525 * +--------------------+--------------------+ 526 * | tail offset | head offset | 527 * +--------------------+--------------------+ 528 * 63 32 31 0 529 * 530 * Run at PIL 14 unless we're already at PIL 15. 531 */ 532 sllx %g3, 32, %g3 ! %g3.h = tail offset 533 or %g3, %g2, %g3 ! %g3.l = head offset 534 rdpr %tl, %g2 ! %g2 = current tl 535 536 /* 537 * Now check if the first error that sent us here was caused 538 * in user's SPILL/FILL trap. If it was, we call sys_trap to 539 * kill the user process. Several considerations: 540 * - If multiple nonresumable errors happen, we only check the 541 * first one. Nonresumable errors cause system either panic 542 * or kill the user process. So the system has already 543 * panic'ed or killed user process after processing the first 544 * error. Therefore, no need to check if other error packet 545 * for this type of error. 546 * - Errors happen in user's SPILL/FILL trap will bring us at 547 * TL = 2. 548 * - We need to lower TL to 1 to get the trap type and tstate. 549 * We don't go back to TL = 2 so no need to save states. 550 */ 551 cmp %g2, 2 552 bne,pt %xcc, 3f ! if tl != 2 553 nop 554 /* Check to see if the trap pc is in a window spill/fill handling */ 555 rdpr %tpc, %g4 556 /* tpc should be in the trap table */ 557 set trap_table, %g5 558 cmp %g4, %g5 559 blu,pt %xcc, 3f 560 nop 561 set etrap_table, %g5 562 cmp %g4, %g5 563 bgeu,pt %xcc, 3f 564 nop 565 /* Set tl to 1 in order to read tt[1] and tstate[1] */ 566 wrpr %g0, 1, %tl 567 rdpr %tt, %g4 ! %g4 = tt[1] 568 /* Check if tt[1] is a window trap */ 569 and %g4, WTRAP_TTMASK, %g4 570 cmp %g4, WTRAP_TYPE 571 bne,pt %xcc, 3f 572 nop 573 rdpr %tstate, %g5 ! %g5 = tstate[1] 574 btst TSTATE_PRIV, %g5 575 bnz %xcc, 3f ! Is it from user code? 576 nop 577 /* 578 * Now we know the error happened in user's SPILL/FILL trap. 579 * Turn on the user spill/fill flag in %g2 580 */ 581 mov 1, %g4 582 sllx %g4, ERRH_U_SPILL_FILL_SHIFT, %g4 583 or %g2, %g4, %g2 ! turn on flag in %g2 584 5853: sub %g2, 1, %g2 ! %g2.l = previous tl 586 587 set process_nonresumable_error, %g1 588 rdpr %pil, %g4 589 cmp %g4, PIL_14 590 ba sys_trap 591 movl %icc, PIL_14, %g4 592 593 /* 594 * We are here because the C routine is not able to process 595 * errors in time. So the first 8 bytes of ER in buf has not 596 * been cleared. We call sys_trap to panic. 597 * Run at PIL 14 unless we're already at PIL 15. 598 */ 5991: set nrq_overflow, %g1 600 rdpr %pil, %g4 601 cmp %g4, PIL_14 602 ba sys_trap 603 movl %icc, PIL_14, %g4 604 6050: retry 606 607 /*NOTREACHED*/ 608 SET_SIZE(nonresumable_error) 609#endif /* lint */ 610