@@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow:
376
376
beqz a2 , 1f # if at start of vector, don't restore
377
377
378
378
addi a0 , a0 , -128
379
- bbsi a0 , 8 , 1f # don't restore except for overflow 8 and 12
380
- bbsi a0 , 7 , 2f
379
+ bbsi.l a0 , 8 , 1f # don't restore except for overflow 8 and 12
380
+
381
+ /*
382
+ * This fixup handler is for the extremely unlikely case where the
383
+ * overflow handler's reference thru a0 gets a hardware TLB refill
384
+ * that bumps out the (distinct, aliasing) TLB entry that mapped its
385
+ * prior references thru a9/a13, and where our reference now thru
386
+ * a9/a13 gets a 2nd-level miss exception (not hardware TLB refill).
387
+ */
388
+ movi a2 , window_overflow_restore_a0_fixup
389
+ s32i a2 , a3 , EXC_TABLE_FIXUP
390
+ l32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
391
+ xsr a3 , excsave1
392
+
393
+ bbsi.l a0 , 7 , 2f
381
394
382
395
/*
383
396
* Restore a0 as saved by _WindowOverflow8().
384
- *
385
- * FIXME: we really need a fixup handler for this L32E,
386
- * for the extremely unlikely case where the overflow handler's
387
- * reference thru a0 gets a hardware TLB refill that bumps out
388
- * the (distinct, aliasing) TLB entry that mapped its prior
389
- * references thru a9, and where our reference now thru a9
390
- * gets a 2nd-level miss exception (not hardware TLB refill).
391
397
*/
392
398
393
- l32e a2 , a9, -16
394
- wsr a2 , depc # replace the saved a0
395
- j 1f
399
+ l32e a0 , a9, -16
400
+ wsr a0 , depc # replace the saved a0
401
+ j 3f
396
402
397
403
2 :
398
404
/*
399
405
* Restore a0 as saved by _WindowOverflow12().
400
- *
401
- * FIXME: we really need a fixup handler for this L32E,
402
- * for the extremely unlikely case where the overflow handler's
403
- * reference thru a0 gets a hardware TLB refill that bumps out
404
- * the (distinct, aliasing) TLB entry that mapped its prior
405
- * references thru a13, and where our reference now thru a13
406
- * gets a 2nd-level miss exception (not hardware TLB refill).
407
406
*/
408
407
409
- l32e a2 , a13, -16
410
- wsr a2 , depc # replace the saved a0
408
+ l32e a0 , a13, -16
409
+ wsr a0 , depc # replace the saved a0
410
+ 3 :
411
+ xsr a3 , excsave1
412
+ movi a0 , 0
413
+ s32i a0 , a3 , EXC_TABLE_FIXUP
414
+ s32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
411
415
1 :
412
416
/*
413
417
* Restore WindowBase while leaving all address registers restored.
@@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow:
449
453
450
454
s32i a0 , a2 , PT_DEPC
451
455
456
+ _DoubleExceptionVector_handle_exception:
452
457
addx4 a0 , a0 , a3
453
458
l32i a0 , a0 , EXC_TABLE_FAST_USER
454
459
xsr a3 , excsave1
@@ -464,10 +469,119 @@ _DoubleExceptionVector_WindowOverflow:
464
469
rotw -3
465
470
j 1b
466
471
467
- .end literal_prefix
468
472
469
473
ENDPROC (_DoubleExceptionVector)
470
474
475
+ /*
476
+ * Fixup handler for TLB miss in double exception handler for window owerflow.
477
+ * We get here with windowbase set to the window that was being spilled and
478
+ * a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12
479
+ * (bit set) window.
480
+ *
481
+ * We do the following here:
482
+ * - go to the original window retaining a0 value;
483
+ * - set up exception stack to return back to appropriate a0 restore code
484
+ * (we'll need to rotate window back and there's no place to save this
485
+ * information, use different return address for that);
486
+ * - handle the exception;
487
+ * - go to the window that was being spilled;
488
+ * - set up window_overflow_restore_a0_fixup as a fixup routine;
489
+ * - reload a0;
490
+ * - restore the original window;
491
+ * - reset the default fixup routine;
492
+ * - return to user. By the time we get to this fixup handler all information
493
+ * about the conditions of the original double exception that happened in
494
+ * the window overflow handler is lost, so we just return to userspace to
495
+ * retry overflow from start.
496
+ *
497
+ * a0: value of depc, original value in depc
498
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
499
+ * a3: exctable, original value in excsave1
500
+ */
501
+
502
+ ENTRY (window_overflow_restore_a0_fixup)
503
+
504
+ rsr a0 , ps
505
+ extui a0 , a0 , PS_OWB_SHIFT, PS_OWB_WIDTH
506
+ rsr a2 , windowbase
507
+ sub a0 , a2 , a0
508
+ extui a0 , a0 , 0 , 3
509
+ l32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
510
+ xsr a3 , excsave1
511
+
512
+ _beqi a0 , 1 , .Lhandle_1
513
+ _beqi a0 , 3 , .Lhandle_3
514
+
515
+ .macro overflow_fixup_handle_exception_pane n
516
+
517
+ rsr a0 , depc
518
+ rotw -\n
519
+
520
+ xsr a3 , excsave1
521
+ wsr a2 , depc
522
+ l32i a2 , a3 , EXC_TABLE_KSTK
523
+ s32i a0 , a2 , PT_AREG0
524
+
525
+ movi a0 , .Lrestore_\n
526
+ s32i a0 , a2 , PT_DEPC
527
+ rsr a0 , exccause
528
+ j _DoubleExceptionVector_handle_exception
529
+
530
+ .endm
531
+
532
+ overflow_fixup_handle_exception_pane 2
533
+ .Lhandle_1:
534
+ overflow_fixup_handle_exception_pane 1
535
+ .Lhandle_3:
536
+ overflow_fixup_handle_exception_pane 3
537
+
538
+ .macro overflow_fixup_restore_a0_pane n
539
+
540
+ rotw \n
541
+ /* Need to preserve a0 value here to be able to handle exception
542
+ * that may occur on a0 reload from stack. It may occur because
543
+ * TLB miss handler may not be atomic and pointer to page table
544
+ * may be lost before we get here. There are no free registers,
545
+ * so we need to use EXC_TABLE_DOUBLE_SAVE area.
546
+ */
547
+ xsr a3 , excsave1
548
+ s32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
549
+ movi a2 , window_overflow_restore_a0_fixup
550
+ s32i a2 , a3 , EXC_TABLE_FIXUP
551
+ l32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
552
+ xsr a3 , excsave1
553
+ bbsi.l a0 , 7 , 1f
554
+ l32e a0 , a9, -16
555
+ j 2f
556
+ 1 :
557
+ l32e a0 , a13, -16
558
+ 2 :
559
+ rotw -\n
560
+
561
+ .endm
562
+
563
+ .Lrestore_2:
564
+ overflow_fixup_restore_a0_pane 2
565
+
566
+ .Lset_default_fixup:
567
+ xsr a3 , excsave1
568
+ s32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
569
+ movi a2 , 0
570
+ s32i a2 , a3 , EXC_TABLE_FIXUP
571
+ l32i a2 , a3 , EXC_TABLE_DOUBLE_SAVE
572
+ xsr a3 , excsave1
573
+ rfe
574
+
575
+ .Lrestore_1:
576
+ overflow_fixup_restore_a0_pane 1
577
+ j .Lset_default_fixup
578
+ .Lrestore_3:
579
+ overflow_fixup_restore_a0_pane 3
580
+ j .Lset_default_fixup
581
+
582
+ ENDPROC (window_overflow_restore_a0_fixup)
583
+
584
+ .end literal_prefix
471
585
/*
472
586
* Debug interrupt vector
473
587
*
0 commit comments