Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / huron / src / errors_common.s
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: errors_common.s
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49#pragma ident "@(#)errors_common.s 1.5 07/08/01 SMI"
50
51#include <sys/asm_linkage.h>
52#include <sun4v/asi.h>
53#include <sun4v/traps.h>
54#include <sun4v/queue.h>
55#include <hypervisor.h>
56#include <guest.h>
57#include <asi.h>
58#include <mmu.h>
59#include <hprivregs.h>
60#include <cache.h>
61#include <dram.h>
62#include <ncu.h>
63
64#include <cmp.h>
65#include <abort.h>
66
67#include <offsets.h>
68#include <util.h>
69#include <legion.h>
70#include <errs_common.h>
71#include <error_defs.h>
72#include <error_regs.h>
73#include <error_asm.h>
74
75/*
76 * Just a short note to document the error handling
77 * implementation. Each error type has an error_table entry which
78 * mandates how that error is corrected, reported, which guest
79 * Queue is used (if any), etc. The trap handler for the error
80 * uses the trap-specific array of error entries to identify the
81 * individual error which has occurred, passing a table entry to the
82 * generic error handler for processing. The error_handler
83 * looks at the error_flags/error_functions encoded in the error_table
84 * entry to determine how the error is to be dealt with,
85 * yanking the error-specific functionality from the table and executing it.
86 *
87 * The processing is as follows :-
88 * 1) Create sun4v guest report
89 * 2) Gather data for SP Diagnosis Engine
90 * 3) Perform any error correction
91 * 4) Set up storm handler if required
92 * 5) Send diagnosis report to SP
93 * 6) Queue guest error report
94 * 7) Exit
95 */
96
97
98 /*
99 * This is the common entry point for all errors. The various
100 * trap handlers will have determined the error type, located
101 * the error_table_entry for that error and transferred control
102 * to here.
103 *
104 * %g1 &error_table_entry
105 */
106 ENTRY(error_handler)
107
108 /*
109 * First we store the address of the error_table-entry
110 * in cpu->cpu_err_table_entry[TL]
111 */
112 SET_ERR_TABLE_ENTRY(%g1, %g2, %g3)
113
114 /*
115 * Check if this error requires an immediate warm reset
116 */
117 ld [%g1 + ERR_FLAGS], %g4
118 set ERR_FORCE_SIR, %g3
119 btst %g3, %g4
120 bz,pt %xcc, error_handler_check_io_prot
121 nop
122
123 PRINT("Software Reset required after Fatal Error!\r\n")
124
125 ! reset the system, an SIR with %o0 = 1 is treated as a fatal reset
126 mov 1, %o0
127 sir 0
128
129error_handler_check_io_prot:
130 /*
131 * Check if this error occurred with strand error protection
132 * enabled. This is only enabled from inside the error handling
133 * code to facilitate checking for stuck-at errors, false error
134 * conditions, etc.
135 */
136 STRAND_STRUCT(%g4)
137 lduw [%g4 + STRAND_ERR_FLAG], %g4
138 set STRAND_ERR_FLAG_PROTECTION, %g5
139 btst %g4, %g5
140 bnz,pn %xcc, 1f
141 nop
142
143 /*
144 * If this error occurred during peek/poke operation with
145 * protection set we just complete the instruction. First
146 * check whether this error type supports I/O protection
147 */
148 ld [%g1 + ERR_FLAGS], %g4
149 btst ERR_IO_PROT, %g4
150 bz,pn %xcc, error_handler_sun4v_reporting ! no I/O protection
151 nop
152
153 STRAND_STRUCT(%g2)
154 set STRAND_IO_PROT, %g3
155 ldx [%g2 + %g3], %g3 ! strand.io_prot
156 brz %g3, error_handler_sun4v_reporting ! if zero, no error protection
157 nop
158
159 /*
160 * Error occurred under i/o error protection
161 * Set the i/o error flag in the strand structure and complete the
162 * instruction
163 */
1641:
165 STRAND_STRUCT(%g2)
166 add %g2, STRAND_IO_ERROR, %g2
167 mov 1, %g3
168 stx %g3, [%g2] ! strand.io_error = 1
169
170 /*
171 * Do any required error correction
172 */
173 ldx [%g1 + ERR_CORRECT_FCN], %g3
174 brz,pn %g3, 1f
175 nop
176
177 HVJMP(%g3, %g7)
178
179 HVCALL(clear_dram_l2c_esr_regs)
180
181 GET_ERR_TABLE_ENTRY(%g1, %g2)
182 ld [%g1 + ERR_FLAGS], %g4
183 set ERR_CLEAR_AMB_ERRORS, %g2
184 btst %g2, %g4
185 bz,pn %xcc, 1f
186 nop
187
188 HVCALL(clear_amb_errors)
189 GET_ERR_TABLE_ENTRY(%g1, %g2)
190 ld [%g1 + ERR_FLAGS], %g4
1911:
192 /*
193 * Does the trap handler for this error park the strands ?
194 * If yes, resume them here.
195 */
196 btst ERR_STRANDS_PARKED, %g4
197 bz,pn %xcc, 1f
198 nop
199
200 RESUME_ALL_STRANDS(%g2, %g3, %g5, %g6)
2011:
202 /*
203 * check whether we stored the globals and re-used
204 * at MAXPTL
205 */
206 btst ERR_GL_STORED, %g4
207 bz,pt %xcc, 1f
208 nop
209
210 RESTORE_GLOBALS(done)
211
2121:
213 /*
214 * All done ..... get out of here
215 */
216
217 done ! complete the instruction
218
219error_handler_sun4v_reporting:
220
221#ifdef DEBUG
222 PRINT_ERROR_TABLE_ENTRY()
223 GET_ERR_TABLE_ENTRY(%g1, %g2)
224#endif
225
226
227 /*
228 * Do any required SUN4V guest error reporting
229 */
230 ldub [%g1 + ERR_SUN4V_RPRT_TYPE], %g3
231 cmp %g3, SUN4V_NO_REPORT
232 be,pn %xcc, error_handler_diag_reporting
233 nop
234
235 HVCALL(error_handler_sun4v_report)
236
237 /*
238 * Must ensure that we get a sun4v report buffer
239 */
240 GET_ERR_SUN4V_RPRT_BUF(%g2, %g3)
241 brz %g2, error_handler_sun4v_reporting
242 nop
243
244 ! Note: %g1 preserved across call
245
246 /*
247 * Call the guest error_specific sun4v report function
248 * This function should be used for ASI report types to load
249 * the ASI/RA fields of the sun4v guest report
250 * PCI-E reports will fill in the DESC attributes
251 */
252 ldx [%g1 + ERR_GUEST_REPORT_FCN], %g3
253 brz,pn %g3, error_handler_diag_reporting
254 nop
255
256 HVJMP(%g3, %g7)
257
258 GET_ERR_TABLE_ENTRY(%g1, %g2)
259
260error_handler_diag_reporting:
261 /*
262 * Do any required SP diagnosis error reporting
263 */
264 ldx [%g1 + ERR_REPORT_FCN], %g3
265 brz,pn %g3, error_handler_correction
266 nop
267
268 /*
269 * First set up the generic report
270 */
271 HVCALL(error_handler_diag_report)
272 GET_ERR_TABLE_ENTRY(%g1, %g2)
273
274 /*
275 * call the error-specific reporting function
276 */
277 ldx [%g1 + ERR_REPORT_FCN], %g3
278 HVJMP(%g3, %g7)
279
280 GET_ERR_TABLE_ENTRY(%g1, %g2)
281
282error_handler_correction:
283 /*
284 * Do any required error correction
285 */
286 ldx [%g1 + ERR_CORRECT_FCN], %g3
287 brz,pn %g3, error_handler_amb_errors
288 nop
289
290 HVJMP(%g3, %g7)
291
292 GET_ERR_TABLE_ENTRY(%g1, %g2)
293
294error_handler_amb_errors:
295 ld [%g1 + ERR_FLAGS], %g4
296 set ERR_CLEAR_AMB_ERRORS, %g2
297 btst %g2, %g4
298 bz,pn %xcc, error_handler_storm
299 nop
300
301 HVCALL(clear_amb_errors)
302 GET_ERR_TABLE_ENTRY(%g1, %g2)
303
304error_handler_storm:
305 /*
306 * If we need to set up any defences against error storms
307 * for this error type, do it now
308 */
309 ldx [%g1 + ERR_STORM_FCN], %g3
310 brz,pn %g3, error_handler_epilog
311 nop
312
313 HVJMP(%g3, %g7)
314
315 GET_ERR_TABLE_ENTRY(%g1, %g2)
316
317error_handler_epilog:
318
319#ifdef DEBUG
320 /*
321 * dump out Service Error Report (SER)
322 * and diag buf data
323 */
324#ifdef DEBUG_LEGION
325 HVCALL(print_diag_ser)
326 HVCALL(print_diag_buf)
327#endif
328 GET_ERR_TABLE_ENTRY(%g1, %g2)
329
330 /*
331 * The error-specific data now ...
332 */
333 ldx [%g1 + ERR_PRINT_FCN], %g3
334 brz,pn %g3, 1f
335 nop
336
337 HVJMP(%g3, %g7)
338
339 GET_ERR_TABLE_ENTRY(%g1, %g2)
3401:
341#endif
342 /*
343 * Does the trap handler for this error park the strands ?
344 * If yes, resume them here.
345 */
346 ld [%g1 + ERR_FLAGS], %g2
347 btst ERR_STRANDS_PARKED, %g2
348 bz,pn %xcc, 1f
349 nop
350
351 RESUME_ALL_STRANDS(%g2, %g4, %g5, %g6)
3521:
353 /*
354 * I have a vision of using an asynchronous cyclic
355 * to send the diagnostic reports to the SP. This cyclic
356 * will trigger and scan through all the err_diag_rprt's
357 * looking for ERR_RPRT_PENDING entries and send them off.
358 * This will cut down the time spent in the error
359 * handler.
360 *
361 * For the moment, this is just a dream, we will just call
362 * the report transmission directly.
363 */
364 ldx [%g1 + ERR_REPORT_FCN], %g3
365 brz,pn %g3, error_handler_resumable
366 nop
367
368 /*
369 * send the report to the SP
370 * send_diag_erpt() will clear the in_use flag
371 * %g1 err_diag_rprt
372 * %g2 err_diag_rprt.err_diag.in_use
373 * %g3 sizeof(err_diag_rprt)
374 */
375 GET_ERR_DIAG_BUF(%g1, %g5)
376 add %g1, ERR_DIAG_RPRT_IN_USE, %g2
377 add %g1, ERR_DIAG_RPRT_REPORT_SIZE, %g3
378 lduw [%g3], %g3
379 HVCALL(send_diag_erpt)
380
381 ! Note: %g1 not preserved across call
382 GET_ERR_TABLE_ENTRY(%g1, %g2)
383
384error_handler_resumable:
385
386 /*
387 * Check if this CPU has been marked bad, if so mark the
388 * corresponding strand in error
389 */
390 VCPU_STRUCT(%g2)
391 ldx [%g2 + CPU_STATUS], %g2
392 cmp %g2, CPU_STATE_ERROR
393 be,pn %xcc, strand_in_error
394 nop
395
396 /*
397 * If this is a FATAL error we will abort the HV now.
398 * No report goes to the guest in this case
399 */
400 ld [%g1 + ERR_FLAGS], %g2
401 btst ERR_FATAL, %g2
402 bnz,pn %xcc, fatal_error
403 nop
404
405 /*
406 * For some L2$ errors, if the line was not dirty
407 * we can continue without terminating the guest
408 */
409 ld [%g1 + ERR_FLAGS], %g2
410 btst ERR_CHECK_LINE_STATE, %g2
411 bz,pn %xcc, 1f
412 nop
413
414 GET_ERR_DIAG_DATA_BUF(%g4, %g5)
415 ldx [%g4 + ERR_DIAG_L2_LINE_STATE], %g5
416 cmp %g5, L2_LINE_DIRTY
417 bne %xcc, error_handler_erpt_done
418 nop
4191:
420
421 /*
422 * check if this is a non-resumable error
423 */
424 ld [%g1 + ERR_FLAGS], %g2
425 btst ERR_NON_RESUMABLE, %g2
426 bnz,pn %xcc, error_handler_non_resumable
427 nop
428
429 /*
430 * No report to guest if the error occurred in the hypervisor
431 */
432 rdpr %tl, %g2
433 brz,pn %g2, 1f
434 nop
435
436 rdhpr %htstate, %g2
437 btst HTSTATE_HPRIV, %g2
438 bnz %xcc, error_handler_erpt_done
439 nop
440
4411:
442
443 /*
444 * Send a resumable error report to the guest if
445 * required.
446 */
447 ldub [%g1 + ERR_SUN4V_RPRT_TYPE], %g2
448 cmp %g2, SUN4V_NO_REPORT
449 be,pt %xcc, error_handler_erpt_done
450 nop
451
452 /*
453 * If the ATTR field in the sun4v report has been set to
454 * zero, we do not want to send this report. This will have
455 * been done in the error handling code which populates the
456 * report when it is determined that the error occurred
457 * on some hyperprivileged register.
458 */
459 GET_ERR_SUN4V_RPRT_BUF(%g3, %g4)
460 ld [%g3 + ERR_SUN4V_RPRT_ATTR], %g4 ! attr
461 brz,pn %g4, error_handler_erpt_done
462 nop
463
464 /*
465 * Sun4v guest resumable error interrupt
466 */
467#ifdef DEBUG
468 PRINT_NOTRAP("queue resumable erpt\r\n");
469 GET_ERR_TABLE_ENTRY(%g1, %g2)
470#endif
471 HVCALL(errors_queue_resumable_erpt)
472 GET_ERR_TABLE_ENTRY(%g1, %g2)
473
474error_handler_erpt_done:
475
476 ld [%g1 + ERR_FLAGS], %g2
477 btst ERR_ISSUE_DONE, %g2
478 bnz,pn %xcc, error_handler_done
479 .empty
480
481 /*
482 * fall through to RETRY
483 */
484
485error_handler_retry:
486
487 /*
488 * check whether we stored the globals and re-used
489 * at MAXPTL
490 */
491 btst ERR_GL_STORED, %g2
492 bz,pt %xcc, 1f
493 nop
494
495 RESTORE_GLOBALS(retry)
4961:
497 /*
498 * And back we go
499 */
500 retry
501
502error_handler_done:
503 /*
504 * check whether we stored the globals and re-used
505 * at MAXPTL
506 */
507 btst ERR_GL_STORED, %g2
508 bz,pt %xcc, 1f
509 nop
510
511 RESTORE_GLOBALS(done)
512
5131:
514 /*
515 * All done ..... get out of here
516 */
517 done
518
519error_handler_non_resumable:
520 PRINT_NOTRAP("error_handler_non_resumable\r\n");
521
522 /*
523 * Abort if the error occurred in the hypervisor itself.
524 */
525 rdhpr %htstate, %g2
526 btst HTSTATE_HPRIV, %g2
527 bnz %xcc, hpriv_error
528 nop
529
530 /*
531 * queue a report on the non-resumable error queue
532 * and then jump to the guests non-resumable trap
533 * handler function
534 */
535 ldub [%g1 + ERR_SUN4V_RPRT_TYPE], %g2
536 cmp %g2, SUN4V_NO_REPORT
537 be,pt %xcc, abort_bad_guest_err_queue
538 nop
539
540 /*
541 * If the ATTR field in the sun4v report has been set to
542 * zero, we do not want to send this report. This will have
543 * been done in the error handling code which populates the
544 * report when it is determined that the error occurred
545 * on some hyperprivileged register.
546 */
547 GET_ERR_SUN4V_RPRT_BUF(%g3, %g4)
548 ld [%g3 + ERR_SUN4V_RPRT_ATTR], %g4 ! attr
549 brz,pn %g4, hpriv_error
550 nop
551
552 ba nonresumable_guest_trap
553 .empty
554
555 SET_SIZE(error_handler)
556
557 /*
558 * allocate a SUN4V report and fill it in.
559 * %g1 &error_table_entry (preserved)
560 * %g3 Sun4v report attribute
561 * %g7 return address
562 */
563 ENTRY(error_handler_sun4v_report)
564
565 /*
566 * Go through the array of err_sun4v_rprt looking
567 * for in_use = 0.
568 */
569 setx err_sun4v_rprt, %g2, %g4
570 RELOC_OFFSET(%g2, %g5)
571 sub %g4, %g5, %g4
572 add %g4, ERR_SUN4V_RPRT_IN_USE, %g4
573 mov MAX_ERROR_REPORT_BUFS, %g5
5741:
575 ldstub [%g4], %g6 ! in_use
576 brz,a,pt %g6, 2f
577 sub %g4, ERR_SUN4V_RPRT_IN_USE, %g4 ! back to &err_sunv_rprt
578
579 /*
580 * This err-sun4v_rprt is in use, go again
581 */
582 dec %g5
583 brz,a,pn %g5, error_handler_sun4v_report_exit
584 clr %g4 ! no buf available
585 ba 1b ! try next buffer
586 add %g4, ERR_SUN4V_RPRT_SIZE, %g4
587
5882:
589 brz,pn %g4, error_handler_sun4v_report_exit
590 .empty
591
592 /*
593 * First we store the address of the err_sun4v_rprt
594 * in strand->strand_sun4v_rprt_buf[TL]
595 */
596 STRAND_STRUCT(%g2)
597 rdpr %tl, %g5
598 dec %g5
599 mulx %g5, STRAND_SUN4V_RPRT_BUF_INCR, %g5
600 add %g5, STRAND_SUN4V_RPRT_BUF, %g5
601 stx %g4, [%g2 + %g5]
602
603 /*
604 * PCI-E or sun4v error report ?
605 */
606 cmp %g3, SUN4V_PCIE_RPRT
607 be,pn %xcc, error_handler_sun4v_pcie_report
608 nop
609
610 /*
611 * Attr field in error table entry is the bit position, need to shift
612 * it to the actual value now.
613 */
614 mov 1, %g5
615 sllx %g5, %g3, %g3
616
617 /*
618 * Fill in the sun4v guest report
619 */
620 ! error_table_entry->err_sun4v_edesc
621 ldub [%g1 + ERR_SUN4V_EDESC], %g5
622 srl %g5, EDESC_TYPE_SHIFT, %g5
623 and %g5, EDESC_TYPE_MASK, %g5
624 st %g5, [%g4 + ERR_SUN4V_RPRT_EDESC]
625 ! strand->strand-id
626 ldub [%g2 + STRAND_ID], %g5
627 stuh %g5, [%g4 + ERR_SUN4V_RPRT_G_CPUID]
628 GENERATE_EHDL(%g6, %g5)
629 stx %g6, [%g4 + ERR_SUN4V_RPRT_G_EHDL]
630 GET_ERR_STICK(%g5)
631 stx %g5, [%g4 + ERR_SUN4V_RPRT_G_STICK]
632
633 /*
634 * Set the MODE, bits [25:24] of the ATTR field
635 */
636 rdpr %tstate, %g5
637 srlx %g5, TSTATE_PSTATE_SHIFT, %g5
638 and %g5, PSTATE_PRIV, %g5
639 movrz %g5, ATTR_USER_MODE, %g6 ! PSTATE.PRIV == 0, User mode
640 movrnz %g5, ATTR_PRIV_MODE, %g6 ! PSTATE.PRIV != 0, Privileged mode
641 sllx %g6, ATTR_MODE_SHIFT, %g6
642 or %g3, %g6, %g3 ! %g3 ATTR, %g6 MODE
643
644 st %g3, [%g4 + ERR_SUN4V_RPRT_ATTR]
645
646 /*
647 * The error-specific data will be filled in later.
648 */
649 setx CPU_ERR_INVALID_RA, %g3, %g5
650 stx %g5, [%g4 + ERR_SUN4V_RPRT_ADDR]
651 st %g0, [%g4 + ERR_SUN4V_RPRT_SZ]
652 stub %g0, [%g4 + ERR_SUN4V_RPRT_ASI]
653 ba error_handler_sun4v_report_exit
654 nop
655
656error_handler_sun4v_pcie_report:
657 GENERATE_EHDL(%g6, %g5)
658 stx %g6, [%g4 + ERR_SUN4V_PCIE_EHDL]
659 GET_ERR_STICK(%g5)
660 stx %g5, [%g4 + ERR_SUN4V_PCIE_STICK]
661 stx %g0, [%g4 + ERR_SUN4V_PCIE_SYSINO]
662 st %g0, [%g4 + ERR_SUN4V_PCIE_DESC]
663 st %g0, [%g4 + ERR_SUN4V_PCIE_SPECIFIC]
664 stx %g0, [%g4 + ERR_SUN4V_PCIE_WORD4]
665 stx %g0, [%g4 + ERR_SUN4V_PCIE_HDR1]
666 stx %g0, [%g4 + ERR_SUN4V_PCIE_HDR2]
667
668error_handler_sun4v_report_exit:
669
670 HVRET
671
672 SET_SIZE(error_handler_sun4v_report)
673
674 /*
675 * allocate a DIAG report buffer
676 * fill in common data
677 *
678 * %g1 &error_table_entry (preserved)
679 * %g7 return address
680 */
681 ENTRY(error_handler_diag_report)
682
683 /*
684 * Go through the array of err_diag_rprt looking
685 * for in_use = 0.
686 */
687 setx err_diag_rprt, %g2, %g4
688 RELOC_OFFSET(%g2, %g5)
689 sub %g4, %g5, %g4
690 add %g4, ERR_DIAG_RPRT_IN_USE, %g4
691 mov MAX_ERROR_REPORT_BUFS, %g5
692 setx ERR_DIAG_RPRT_SIZE, %g3, %g6
6931:
694 /*
695 * The in_use flag is a 32-bit int to maintain compatibility
696 * with svc_internal_send(). We use only the bottom eight
697 * bits, hence the '+ 3'.
698 */
699 ldstub [%g4 + 3], %g2 ! in_use
700 brz,a,pt %g2, 2f ! REPORT_BUF_FREE
701 sub %g4, ERR_DIAG_RPRT_IN_USE, %g4 ! back to &err_diag_rprt
702
703 /*
704 * This err_diag_rprt is in use, go again
705 */
706 dec %g5
707 brz,a,pn %g5, error_handler_diag_report_exit
708 clr %g4 ! no buf available
709
710 ba 1b ! try next buffer
711 add %g4, %g6, %g4
712
7132:
714 brz,pn %g4, error_handler_diag_report_exit
715 .empty
716
717 /*
718 * First we store the address of the err_diag_rprt
719 * in strand->strand_err_diag_buf[TL]
720 */
721 STRAND_STRUCT(%g2)
722 rdpr %tl, %g3
723 dec %g3
724 mulx %g3, STRAND_DIAG_BUF_INCR, %g5
725 add %g5, STRAND_DIAG_BUF, %g5
726 stx %g4, [%g2 + %g5]
727
728 add %g4, ERR_DIAG_RPRT_IN_USE, %g3
729 mov REPORT_BUF_PENDING, %g5
730 st %g5, [%g3]
731
732 /*
733 * Fill in the generic SP diagnosis report data
734 * If we already have an EHDL in the Sun4v report just get
735 * that sequence number
736 */
737 GET_ERR_SUN4V_RPRT_BUF(%g5, %g3)
738 brz,pt %g5, 1f
739 nop
740
741 ldub [%g1 + ERR_SUN4V_RPRT_TYPE], %g3
742 cmp %g3, SUN4V_PCIE_RPRT
743 mov ERR_SUN4V_PCIE_EHDL, %g3
744 movne %xcc, ERR_SUN4V_RPRT_G_EHDL, %g3
745 ldx [%g5 + %g3], %g5
746 ba 2f
747 nop
748
7491:
750 /*
751 * generate a new strand sequence number
752 */
753 GENERATE_EHDL(%g5, %g3)
7542:
755 stx %g5, [%g4 + ERR_DIAG_RPRT_EHDL]
756 mov ERPT_TYPE_CPU, %g5
757 stx %g5, [%g4 + ERR_DIAG_RPRT_ERROR_TYPE]
758 CONFIG_STRUCT(%g5)
759 ldx [%g5 + CONFIG_TOD], %g5
760 brnz,a,pn %g5, 1f
761 ldx [%g5], %g5 ! aborted if no TOD
7621:
763 stx %g5, [%g4 + ERR_DIAG_RPRT_TOD]
764 ! error report type from error_table entry
765 ldub [%g1 + ERR_SUN4V_EDESC], %g5
766 srl %g5, SER_TYPE_SHIFT, %g5
767 and %g5, SER_TYPE_MASK, %g5
768 stx %g5, [%g4 + ERR_DIAG_RPRT_REPORT_TYPE]
769 ! error report size from error_table entry
770 lduw [%g1 + ERR_REPORT_SIZE], %g5
771 stuw %g5, [%g4 + ERR_DIAG_RPRT_REPORT_SIZE]
772 GET_ERR_STICK(%g5)
773 stx %g5, [%g4 + ERR_DIAG_RPRT_ERR_STICK]
774 rdhpr %hver, %g5
775 stx %g5, [%g4 + ERR_DIAG_RPRT_CPUVER]
776 setx NCU_BASE + PROC_SER_NUM, %g5, %g3
777 ldx [%g3], %g5
778 stx %g5, [%g4 + ERR_DIAG_RPRT_SERIAL]
779 ldub [%g2 + STRAND_ID], %g5
780 stuh %g5, [%g4 + ERR_DIAG_RPRT_CPUID]
781 rdpr %tl, %g5
782 stub %g5, [%g4 + ERR_DIAG_RPRT_TL]
783 rdpr %tt, %g5
784 stuh %g5, [%g4 + ERR_DIAG_RPRT_TT]
785 rdpr %tstate, %g5
786 stx %g5, [%g4 + ERR_DIAG_RPRT_TSTATE]
787 rdhpr %htstate, %g5
788 stx %g5, [%g4 + ERR_DIAG_RPRT_HTSTATE]
789 rdpr %tpc, %g5
790 stx %g5, [%g4 + ERR_DIAG_RPRT_TPC]
791
792 /*
793 * Clear the diag_buf ESRs, up to the in_use flag
794 */
795 add %g4, ERR_DIAG_RPRT_ERR_DIAG, %g4
796
797 STRAND_PUSH(%g7, %g1, %g2)
798 mov %g4, %g1
799 mov ERR_DIAG_BUF_RPRT_IN_USE, %g2
800 HVCALL(bzero)
801 STRAND_POP(%g7, %g1)
802
803 /*
804 * store the DESR
805 */
806 GET_ERR_DESR(%g2, %g3)
807 stx %g2, [%g4 + ERR_DIAG_BUF_SPARC_DESR]
808
809 /*
810 * store the DFESR
811 */
812 GET_ERR_DFESR(%g2, %g3)
813 stx %g2, [%g4 + ERR_DIAG_BUF_SPARC_DFESR]
814
815 /*
816 * store the D-SFSR/I-SFSR/D-SFAR
817 */
818 GET_ERR_DSFSR(%g3, %g5)
819 stx %g3, [%g4 + ERR_DIAG_BUF_SPARC_DSFSR]
820 GET_ERR_DSFAR(%g3, %g5)
821 stx %g3, [%g4 + ERR_DIAG_BUF_SPARC_DSFAR]
822 GET_ERR_ISFSR(%g3, %g5)
823 stx %g3, [%g4 + ERR_DIAG_BUF_SPARC_ISFSR]
824
825error_handler_diag_report_exit:
826
827 HVRET
828 SET_SIZE(error_handler_diag_report)
829
830 /*
831 * Send an error report for diagnosis to the SP
832 *
833 * %g1 - %g6 clobbered
834 * %g7 return address
835 */
836 ENTRY(transmit_diag_reports)
837
838 STORE_ERR_RETURN_ADDR(%g7, %g1, %g2)
839
840 /*
841 * Go through the array of err_diag_rprt looking
842 * for in_use = REPORT_BUF_PENDING.
843 */
844transmit_diag_reports_start:
845
846 setx err_diag_rprt, %g2, %g4
847 RELOC_OFFSET(%g2, %g5)
848 sub %g4, %g5, %g4
849 add %g4, ERR_DIAG_RPRT_IN_USE, %g4
850 mov MAX_ERROR_REPORT_BUFS, %g5
851 setx ERR_DIAG_RPRT_SIZE, %g2, %g6
8521:
853 /*
854 * The in_use flag is a 32-bit int to maintain compatibility
855 * with svc_internal_send(). We use only the bottom eight
856 * bits, hence the '+ 3'.
857 */
858 ldub [%g4 + 3], %g2 ! in_use
859 cmp %g2, REPORT_BUF_IN_USE
860 be,a,pt %xcc, 2f
861 sub %g4, ERR_DIAG_RPRT_IN_USE, %g4 ! back to &err_diag_rprt
862
863 /*
864 * This err_diag_rprt is not ready to be sent to the
865 * SP, go again
866 */
867 dec %g5
868 brz,a,pn %g5, transmit_diag_piu_reports
869 clr %g4 ! no buf available
870 ba 1b ! try next buffer
871 add %g4, %g6, %g4
872
8732:
874 /*
875 * send the report to the SP
876 * send_diag_erpt() will clear the in_use flag
877 * %g4 diag_buf
878 */
879 mov %g4, %g1
880 add %g1, ERR_DIAG_RPRT_IN_USE, %g2
881 add %g1, ERR_DIAG_RPRT_REPORT_SIZE, %g3
882 lduw [%g3], %g3
883 HVCALL(send_diag_erpt_nolock)
884
885 ba transmit_diag_reports_exit
886 nop
887
888transmit_diag_piu_reports:
889#ifdef CONFIG_PIU
890 /*
891 * Check whether any PIU error reports are waiting to be transmitted
892 */
893 setx piu_dev, %g2, %g4
894 RELOC_OFFSET(%g2, %g5)
895 sub %g4, %g5, %g4
896 set NPIUS, %g5
897.check_next_piu_dev:
898 ! each piu_dev has two error reports, DMU and PEU
899 ! check the 'unsent' flag on each
900 ! %g4 piu_dev[]
901 add %g4, PIU_COOKIE_DMU_ERPT, %g1
902 ldsw [%g1 + PCI_UNSENT_PKT], %g2
903 brnz,pn %g2, .transmit_piu_dev_err
904 nop
905 add %g4, PIU_COOKIE_PEU_ERPT, %g1
906 ldsw [%g1 + PCI_UNSENT_PKT], %g2
907 brnz,pn %g2, .transmit_piu_dev_err
908 dec %g5
909 brnz,pt %g5, .check_next_piu_dev
910 add %g4, PIU_COOKIE_SIZE, %g4
911
912 ! nothing to send
913 ba transmit_diag_reports_exit
914 nop
915
916.transmit_piu_dev_err:
917 ! PIU error ready to go
918 ! %g1 PIU error report
919 add %g1, PCI_UNSENT_PKT, %g2
920 add %g1, PCI_ERPT_U, %g1
921 mov PCIERPT_SIZE - EPKTSIZE, %g3
922 HVCALL(send_diag_erpt_nolock)
923
924#endif /* CONFIG_PIU */
925
926transmit_diag_reports_exit:
927
928 GET_ERR_RETURN_ADDR(%g7, %g2)
929 HVRET
930
931 SET_SIZE(transmit_diag_reports)
932
933 /*
934 * Jump to the nonresumable_error trap of the privileged code.
935 * Select trap table entry based on TL.
936 */
937 ENTRY(nonresumable_guest_trap)
938
939 PRINT_NOTRAP("nonresumable_guest_trap\r\n");
940 /*
941 * Put the sun4v ereport onto the non-resumable queue for this
942 * guest
943 *
944 * Note that both precise and deferred non-resumable error
945 * reports will be queued on the guests non-resumable error
946 * queue here.
947 *
948 * Note: We don't care about saving our return address (%g7)
949 * here because we are not getting out of here alive.
950 */
951 HVCALL(errors_queue_nonresumable_erpt)
952
953 VCPU_STRUCT(%g1)
954 IS_CPU_IN_ERROR(%g1, %g2)
955 bne %xcc, 1f
956 nop
957
958 ! Mark the corresponding strand in error
959 HVCALL(strand_in_error)
9601:
961 /*
962 * Jump to the nonresumable_error trap of the privileged code.
963 * Select trap table entry based on TL.
964 * Set TT for the guest
965 */
966 wrpr %g0, TT_NONRESUMABLE_ERR, %tt
967
968 /*
969 * ensure that the guest is not entered in an illegal state
970 */
971 GET_ERR_GL(%g1)
972 cmp %g1, MAXPGL
973 bgu,pn %xcc, watchdog_guest
974 rdpr %tl, %g1
975 cmp %g1, MAXPTL
976 bgu,pn %xcc, watchdog_guest
977 .empty
978
979 /*
980 * Build TSTATE from current state for the trap to the
981 * guests non_resumable_error trap table entry.
982 */
983 rdhpr %hpstate, %g3
984 mov PSTATE_PRIV, %g1
985 sllx %g1, TSTATE_PSTATE_SHIFT, %g4
986
987 GET_ERR_CWP(%g1)
988 sllx %g1, TSTATE_CWP_SHIFT, %g1
989 or %g4, %g1, %g4
990 rdpr %tstate, %g1
991 srlx %g1, TSTATE_ASI_SHIFT, %g1
992 and %g1, TSTATE_ASI_MASK, %g1
993 sllx %g1, TSTATE_ASI_SHIFT, %g1
994 or %g4, %g1, %g4
995 rd %ccr, %g1
996 sllx %g1, TSTATE_CCR_SHIFT, %g1
997 or %g4, %g1, %g4
998 GET_ERR_GL(%g1)
999 sllx %g1, TSTATE_GL_SHIFT, %g1
1000 or %g4, %g1, %g4
1001 rdpr %tba, %g1
1002 or %g1, (TT_NONRESUMABLE_ERR << TT_OFFSET_SHIFT), %g1
1003 rdpr %tl, %g2
1004 cmp %g2, 1
1005 be,pt %xcc, 2f ! if TL - 1 == 0, go to 2
1006 set TRAPTABLE_SIZE, %g5 ! set TL bit in trap address
1007 add %g5, %g1, %g1 ! add TL for TL > 1
10082:
1009 /*
1010 * Cache the err_flags before incrementing TL as
1011 * the GET_ERR_TABLE_ENTRY() macro uses TL to find the
1012 * error_table entry for this error
1013 */
1014 GET_ERR_TABLE_ENTRY(%g5, %g6)
1015 ld [%g5 + ERR_FLAGS], %g5
1016
1017 ! %g1 trap_table address
1018 ! %g2 TL
1019 ! %g4 TSTATE
1020 ! %g5 error_table->err_flags
1021 inc %g2
1022 wrpr %g2, %tl
1023 wrpr %g0, TT_NONRESUMABLE_ERR, %tt
1024 wrpr %g1, %tpc
1025 add %g1, 4, %g1
1026 wrpr %g1, %tnpc
1027 wrpr %g4, %tstate
1028 wrhpr %g0, HPSTATE_GUEST, %htstate
1029
1030 /*
1031 * After RETRY we will have :-
1032 * %pc guest non_resumable_error trap table entry
1033 * %npc guest non_resumable_error trap table entry + 4
1034 * %gl Current GL which error handler is running at
1035 * %tl Current TL which error handler is running at
1036 * %tt TT_NONRESUMABLE_ERR
1037 * %tpc PC of UE precise error trap
1038 */
1039
1040 btst ERR_GL_STORED, %g5
1041 bz,pt %xcc, 1f
1042 nop
1043
1044 RESTORE_GLOBALS(retry)
1045
10461:
1047 retry
1048
1049 SET_SIZE(nonresumable_guest_trap)
1050
1051 /*
1052 * Queue a resumable error report on this CPU
1053 *
1054 * %g1 &error_table_entry
1055 * %g2 sun4v report type
1056 * %g7 return address
1057 */
1058 ENTRY_NP(errors_queue_resumable_erpt)
1059
1060 /*
1061 * Before we send a report to the guest, we must make ensure that the
1062 * error actually occurred on hardware resources owned by the guest and
1063 * that the error trap was not simply steered to a CPU owned by the guest.
1064 */
1065 STRAND_PUSH(%g7, %g3, %g4)
1066 STRAND_PUSH(%g2, %g3, %g4)
1067 STRAND_PUSH(%g1, %g3, %g4)
1068 HVCALL(errors_check_steering)
1069 STRAND_POP(%g1, %g3)
1070 STRAND_POP(%g2, %g3)
1071 STRAND_POP(%g7, %g3)
1072
1073 cmp %g2, SUN4V_PCIE_RPRT
1074 bne,pt %xcc, 1f
1075 nop
1076
1077 /*
1078 * PCI-E error interrupt
1079 */
1080 ba queue_pcie_erpt
1081 nop
10821:
1083 STORE_ERR_RETURN_ADDR(%g7, %g1, %g2)
1084 GET_ERR_SUN4V_RPRT_BUF(%g2, %g4)
1085 add %g2, ERR_SUN4V_CPU_ERPT, %g2
1086 HVCALL(queue_resumable_erpt)
1087 ba errors_queue_resumable_erpt_done
1088 nop
1089
1090queue_pcie_erpt:
1091 /*
1092 * insert a dev_mondo using the PCI-E error packet
1093 */
1094 STORE_ERR_RETURN_ADDR(%g7, %g1, %g2)
1095 GET_ERR_SUN4V_RPRT_BUF(%g1, %g4)
1096 add %g1, ERR_SUN4V_PCIE_ERPT, %g1
1097 HVCALL(insert_device_mondo_p)
1098
1099errors_queue_resumable_erpt_done:
1100 /*
1101 * Clear the in_use bit on the sun4v report buffer
1102 */
1103 GET_ERR_SUN4V_RPRT_BUF(%g3, %g4)
1104 stub %g0, [%g3 + ERR_SUN4V_RPRT_IN_USE]
1105 GET_ERR_RETURN_ADDR(%g7, %g2)
1106 HVRET
1107
1108 SET_SIZE(errors_queue_resumable_erpt)
1109
1110
1111 /*
1112 * Queue a nonresumable error report on this CPU
1113 *
1114 * If there is no free entry in the nonresumable error queue
1115 * print a message and abort the guest.
1116 */
1117 ENTRY_NP(errors_queue_nonresumable_erpt)
1118
1119 /*
1120 * Before we send a report to the guest, we must make ensure that the
1121 * error actually occurred on hardware resources owned by the guest and
1122 * that the error trap was not simply steered to a CPU owned by the guest.
1123 */
1124 STRAND_PUSH(%g7, %g3, %g4)
1125 HVCALL(errors_check_steering)
1126 STRAND_POP(%g7, %g3)
1127
1128 STORE_ERR_RETURN_ADDR(%g7, %g1, %g2)
1129 GET_ERR_SUN4V_RPRT_BUF(%g2, %g4)
1130
1131 /*
1132 * If this is a MEM report, set the SZ field here.
1133 */
1134 ld [%g2 + ERR_SUN4V_RPRT_ATTR], %g4 ! attr
1135 mov 1, %g3
1136 sllx %g3, SUN4V_MEM_RPRT, %g3
1137 and %g4, %g3, %g4
1138 brz,pt %g4, 1f
1139 mov ERPT_MEM_SIZE, %g4
1140 st %g4, [%g4 + ERR_SUN4V_RPRT_SZ]
11411:
1142
1143 add %g2, ERR_SUN4V_CPU_ERPT, %g2
1144 HVCALL(queue_nonresumable_erpt)
1145
1146#ifdef DEBUG_LEGION
1147 /*
1148 * print sun4v erpt data to console
1149 */
1150 HVCALL(print_sun4v_erpt)
1151#endif
1152
1153 /*
1154 * Clear the in_use bit on the sun4v report buffer
1155 */
1156 GET_ERR_SUN4V_RPRT_BUF(%g2, %g4)
1157 stub %g0, [%g2 + ERR_SUN4V_RPRT_IN_USE]
1158 GET_ERR_RETURN_ADDR(%g7, %g2)
1159
1160 HVRET
1161 SET_SIZE(errors_queue_nonresumable_erpt)
1162
1163
1164 /*
1165 * %g2 sun4v error report
1166 * %g7 return address
1167 * Returns
1168 * %g1 0 - success; 1 - failure
1169 */
1170 ENTRY(queue_resumable_erpt)
1171 VCPU_STRUCT(%g1)
1172
1173 ldx [%g1 + CPU_ERRQR_BASE_RA], %g3 ! get q base RA
1174 brnz %g3, 1f ! if base RA is zero, skip
1175 nop
1176 ! The resumable error queue is not allocated/initialized
1177 ! simply return. No guest is there to receive it.
1178queue_resumable_erpt_full:
1179 mov 1, %g1 ! failed to queue
1180 HVRET
1181
11821:
1183 mov ERROR_RESUMABLE_QUEUE_TAIL, %g3
1184 ldxa [%g3]ASI_QUEUE, %g5 ! %g5 = rq_tail
1185 add %g5, Q_EL_SIZE, %g6 ! %g6 = rq_next = rq_tail++
1186 ldx [%g1 + CPU_ERRQR_MASK], %g4
1187 and %g6, %g4, %g6 ! %g6 = rq_next mod
1188 mov ERROR_RESUMABLE_QUEUE_HEAD, %g3
1189 ldxa [%g3] ASI_QUEUE, %g4 ! %g4 = rq_head
1190 cmp %g6, %g4 ! head = ++tail?
1191 be %xcc, queue_resumable_erpt_full
1192 mov ERROR_RESUMABLE_QUEUE_TAIL, %g3
1193 stxa %g6, [%g3] ASI_QUEUE ! new tail = rq_next
1194 ! write up the queue record
1195 ! %g2 sun4v ereport buf
1196 ldx [%g1 + CPU_ERRQR_BASE], %g4
1197 add %g5, %g4, %g3 ! %g3 = base + tail
1198 ldx [%g2 + CPU_SUN4V_RPRT_G_EHDL], %g4 ! ehdl
1199 stx %g4, [%g3 + SUN4V_EHDL_OFFSET]
1200 ldx [%g2 + CPU_SUN4V_RPRT_G_STICK], %g4 ! stick
1201 stx %g4, [%g3 + SUN4V_TICK_OFFSET]
1202 ld [%g2 + CPU_SUN4V_RPRT_EDESC], %g4 ! edesc
1203 st %g4, [%g3 + SUN4V_DESC_OFFSET]
1204 ld [%g2 + CPU_SUN4V_RPRT_ATTR], %g4 ! attr
1205 st %g4, [%g3 + SUN4V_ATTR_OFFSET]
1206 ldx [%g2 + CPU_SUN4V_RPRT_ADDR], %g4 ! addr
1207 stx %g4, [%g3 + SUN4V_ADDR_OFFSET]
1208 ld [%g2 + CPU_SUN4V_RPRT_SZ], %g4 ! sz
1209 st %g4, [%g3 + SUN4V_SZ_OFFSET]
1210 lduh [%g2 + CPU_SUN4V_RPRT_G_CPUID], %g4 ! cpuid
1211 stuh %g4, [%g3 + SUN4V_CPUID_OFFSET]
1212 lduh [%g2 + CPU_SUN4V_RPRT_G_SECS], %g4
1213 stuh %g4, [%g3 + SUN4V_SECS_OFFSET] ! secs
1214 ldub [%g2 + CPU_SUN4V_RPRT_ASI], %g4
1215 stub %g4, [%g3 + SUN4V_ASI_OFFSET] ! asi/pad
1216 lduh [%g2 + CPU_SUN4V_RPRT_REG], %g4
1217 stuh %g4, [%g3 + SUN4V_REG_OFFSET] ! reg
1218 st %g0, [%g3 + SUN4V_PAD0_OFFSET]
1219 stx %g0, [%g3 + SUN4V_PAD1_OFFSET]
1220 stx %g0, [%g3 + SUN4V_PAD2_OFFSET]
1221
1222 clr %g1 ! success
1223 HVRET
1224
1225 SET_SIZE(queue_resumable_erpt)
1226
1227
1228 /*
1229 * %g2 sun4v error report
1230 * %g7 return address
1231 * Returns
1232 * %g1 0 - success; 1 - failure
1233 */
1234 ENTRY_NP(queue_nonresumable_erpt)
1235
1236 ! %g1 vcpup
1237 VCPU_STRUCT(%g1)
1238 ! Get the guest structure this vcpu belongs
1239 VCPU2GUEST_STRUCT(%g1, %g5)
1240
1241 ! Determine the guest state
1242 lduw [%g5 + GUEST_STATE], %g4
1243 set GUEST_STATE_SUSPENDED, %g3
1244 cmp %g4, %g3
1245 be,pn %xcc, .check_vcpu_queues
1246 set GUEST_STATE_NORMAL, %g3
1247 cmp %g4, %g3
1248 be,pn %xcc, .check_vcpu_queues
1249 set GUEST_STATE_EXITING, %g3
1250 cmp %g4, %g3
1251 be,pn %xcc, .drop_nrq_pkt
1252 set GUEST_STATE_STOPPED, %g3
1253 cmp %g4, %g3
1254 be,pn %xcc, .drop_nrq_pkt
1255 set GUEST_STATE_UNCONFIGURED, %g3
1256 cmp %g4, %g3
1257 be,pn %xcc, .drop_nrq_pkt
1258 nop
1259
1260.check_vcpu_queues:
1261 ldx [%g1 + CPU_ERRQNR_BASE_RA], %g3 ! get q base RA
1262 brz %g3, abort_missing_guest_err_queue ! if base RA zero, abort
1263 nop
1264
1265 mov ERROR_NONRESUMABLE_QUEUE_TAIL, %g3
1266 ldxa [%g3]ASI_QUEUE, %g5 ! %g5 = rq_tail
1267 add %g5, Q_EL_SIZE, %g6 ! %g6 = rq_next = rq_tail++
1268 ldx [%g1 + CPU_ERRQNR_MASK], %g4
1269 and %g6, %g4, %g6 ! %g6 = rq_next mod
1270 mov ERROR_NONRESUMABLE_QUEUE_HEAD, %g3
1271 ldxa [%g3] ASI_QUEUE, %g4 ! %g4 = rq_head
1272 cmp %g6, %g4 ! head = ++tail?
1273 be %xcc, abort_bad_guest_err_queue
1274 mov ERROR_NONRESUMABLE_QUEUE_TAIL, %g3
1275 stxa %g6, [%g3] ASI_QUEUE ! new tail = rq_next
1276 ! write up the queue record
1277 ! %g2 sun4v ereport buf
1278 ldx [%g1 + CPU_ERRQNR_BASE], %g4
1279 add %g5, %g4, %g3 ! %g3 = base + tail
1280 ldx [%g2 + ERR_SUN4V_RPRT_G_EHDL], %g4 ! ehdl
1281 stx %g4, [%g3 + SUN4V_EHDL_OFFSET]
1282 ldx [%g2 + ERR_SUN4V_RPRT_G_STICK], %g4 ! stick
1283 stx %g4, [%g3 + SUN4V_TICK_OFFSET]
1284 ld [%g2 + ERR_SUN4V_RPRT_EDESC], %g4 ! edesc
1285 st %g4, [%g3 + SUN4V_DESC_OFFSET]
1286 ld [%g2 + ERR_SUN4V_RPRT_ATTR], %g4 ! attr
1287 st %g4, [%g3 + SUN4V_ATTR_OFFSET]
1288 ldx [%g2 + ERR_SUN4V_RPRT_ADDR], %g4 ! addr
1289 stx %g4, [%g3 + SUN4V_ADDR_OFFSET]
1290 ld [%g2 + ERR_SUN4V_RPRT_SZ], %g4 ! sz
1291 st %g4, [%g3 + SUN4V_SZ_OFFSET]
1292 lduh [%g2 + ERR_SUN4V_RPRT_G_CPUID], %g4 ! cpuid
1293 stuh %g4, [%g3 + SUN4V_CPUID_OFFSET]
1294 lduh [%g2 + ERR_SUN4V_RPRT_G_SECS], %g4
1295 stuh %g4, [%g3 + SUN4V_SECS_OFFSET] ! secs
1296 lduh [%g2 + ERR_SUN4V_RPRT_ASI], %g4
1297 stuh %g4, [%g3 + SUN4V_ASI_OFFSET] ! asi/pad
1298 lduh [%g2 + ERR_SUN4V_RPRT_REG], %g4
1299 stuh %g4, [%g3 + SUN4V_REG_OFFSET] ! reg
1300 st %g0, [%g3 + SUN4V_PAD0_OFFSET]
1301 stx %g0, [%g3 + SUN4V_PAD1_OFFSET]
1302 stx %g0, [%g3 + SUN4V_PAD2_OFFSET]
1303
1304 clr %g1 ! success
1305 HVRET
1306
1307.drop_nrq_pkt:
1308 /*
1309 * The guest is not in the proper state to receive pkts
1310 * Drop packet by just returning
1311 */
1312#ifdef DEBUG
1313 mov %g7, %g6
1314 PRINT("no guest to deliver NR error pkt. Dropping it\r\n")
1315 mov %g6, %g7
1316#endif
1317 mov 1, %g1 ! failed to queue
1318 HVRET
1319
1320 /*
1321 * The nonresumable error queue is full.
1322 * Reset the guest
1323 */
1324abort_bad_guest_err_queue:
1325#ifdef DEBUG
1326 mov %g7, %g6
1327 PRINT("queue_nonresumable_erpt: nrq full - exiting guest\r\n")
1328 mov %g6, %g7
1329#endif
1330 SET_CPU_IN_ERROR(%g1, %g2)
1331 ba queue_resumable_erpt
1332 nop
1333
1334abort_missing_guest_err_queue:
1335#ifdef DEBUG
1336 mov %g7, %g6
1337 PRINT("queue_nonresumable_erpt: q missing - exiting guest\r\n")
1338 mov %g6, %g7
1339#endif
1340 mov 1, %g1 ! failed to queue
1341 HVRET
1342
1343 SET_SIZE(queue_nonresumable_erpt)
1344
1345
1346/*
1347 * Uncorrectable error in HV
1348 *
1349 * Note that the diagnosis report should have been sent to the
1350 * SP already
1351 */
1352hpriv_error:
1353#ifdef DEBUG
1354 PRINT("ABORT ON HV UE!\r\n");
1355#endif
1356 HPRIV_ERROR()
1357
1358fatal_error:
1359#ifdef DEBUG
1360 PRINT("ABORT ON FATAL ERROR!\r\n");
1361#endif
1362 FATAL_ERROR()
1363
1364hvabort_exit:
1365
1366 /*
1367 * make sure any outstanding error reports get sent
1368 */
1369 HVCALL(transmit_diag_reports)
1370
1371#ifdef CONFIG_VBSC_SVC
1372 HV_PRINT_NOTRAP(", contacting vbsc\r\n");
1373 ba,pt %xcc, vbsc_hv_abort
1374 rd %pc, %g1
1375#else
1376 HV_PRINT_NOTRAP(", spinning\r\n");
1377 LEGION_EXIT(1)
13782: ba,a 2b
1379 nop
1380#endif