1/* 2 * Window fill (underflow) trap, based on code from Sparclinux. 3 * 4 * Copyright (C) 1995 David S. Miller 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 18 * MA 02110-1301, USA. 19 */ 20 21// #include <psr.h> 22// #include <asi.h> 23 24/* Reg_window offsets */ 25#define RW_L0 0x00 26#define RW_L1 0x04 27#define RW_L2 0x08 28#define RW_L3 0x0c 29#define RW_L4 0x10 30#define RW_L5 0x14 31#define RW_L6 0x18 32#define RW_L7 0x1c 33#define RW_I0 0x20 34#define RW_I1 0x24 35#define RW_I2 0x28 36#define RW_I3 0x2c 37#define RW_I4 0x30 38#define RW_I5 0x34 39#define RW_I6 0x38 40#define RW_I7 0x3c 41 42/* Load a register window from the area beginning at %reg. */ 43#define LOAD_WINDOW(reg) \ 44 ldd [%reg + RW_L0], %l0; \ 45 ldd [%reg + RW_L2], %l2; \ 46 ldd [%reg + RW_L4], %l4; \ 47 ldd [%reg + RW_L6], %l6; \ 48 ldd [%reg + RW_I0], %i0; \ 49 ldd [%reg + RW_I2], %i2; \ 50 ldd [%reg + RW_I4], %i4; \ 51 ldd [%reg + RW_I6], %i6; 52 53#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */ 54 55/* Just like the overflow handler we define macros for registers 56 * with fixed meanings in this routine. 57 */ 58#define t_psr l0 59#define t_pc l1 60#define t_npc l2 61#define t_wim l3 62/* Don't touch the above registers or else you die horribly... */ 63 64/* Now macros for the available scratch registers in this routine. */ 65#define twin_tmp1 l4 66#define twin_tmp2 l5 67 68 .text 69 .align 4 70 71 /* The trap entry point has executed the following: 72 * 73 * rd %psr, %l0 74 * rd %wim, %l3 75 * b fill_window_entry 76 * andcc %l0, PSR_PS, %g0 77 */ 78 79 /* To get an idea of what has just happened to cause this 80 * trap take a look at this diagram: 81 * 82 * 1 2 3 4 <-- Window number 83 * ---------- 84 * T O W I <-- Symbolic name 85 * 86 * O == the window that execution was in when 87 * the restore was attempted 88 * 89 * T == the trap itself has save'd us into this 90 * window 91 * 92 * W == this window is the one which is now invalid 93 * and must be made valid plus loaded from the 94 * stack 95 * 96 * I == this window will be the invalid one when we 97 * are done and return from trap if successful 98 */ 99 100 /* BEGINNING OF PATCH INSTRUCTIONS */ 101 102 /* On 7-window Sparc the boot code patches fnwin_patch1 103 * with the following instruction. 104 */ 105 .globl fnwin_patch1_7win, fnwin_patch2_7win 106fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2 107fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1 108 /* END OF PATCH INSTRUCTIONS */ 109 110 111 .globl fill_window_entry, fnwin_patch1, fnwin_patch2 112fill_window_entry: 113 /* LOCATION: Window 'T' */ 114 115 /* Compute what the new %wim is going to be if we retrieve 116 * the proper window off of the stack. 117 */ 118 sll %t_wim, 1, %twin_tmp1 119fnwin_patch1: srl %t_wim, 7, %twin_tmp2 120 or %twin_tmp1, %twin_tmp2, %twin_tmp1 121fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1 122 123 wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */ 124 125 restore %g0, %g0, %g0 /* Restore to window 'O' */ 126 127 /* Trapped from kernel, we trust that the kernel does not 128 * 'over restore' sorta speak and just grab the window 129 * from the stack and return. Easy enough. 130 */ 131 /* LOCATION: Window 'O' */ 132 133 restore %g0, %g0, %g0 134 WRITE_PAUSE 135 136 /* LOCATION: Window 'W' */ 137 138 LOAD_WINDOW(sp) /* Load it up */ 139 140 /* Spin the wheel... */ 141 save %g0, %g0, %g0 142 save %g0, %g0, %g0 143 /* I'd like to buy a vowel please... */ 144 145 /* LOCATION: Window 'T' */ 146 147 /* Now preserve the condition codes in %psr, pause, and 148 * return from trap. This is the simplest case of all. 149 */ 150 wr %t_psr, 0x0, %psr 151 WRITE_PAUSE 152 153 jmp %t_pc 154 rett %t_npc 155