1*b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 288278ca2SAdrian Bunk/* 31da177e4SLinus Torvalds * wof.S: Sparc window overflow handler. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds#include <asm/contregs.h> 91da177e4SLinus Torvalds#include <asm/page.h> 101da177e4SLinus Torvalds#include <asm/ptrace.h> 111da177e4SLinus Torvalds#include <asm/psr.h> 121da177e4SLinus Torvalds#include <asm/smp.h> 131da177e4SLinus Torvalds#include <asm/asi.h> 141da177e4SLinus Torvalds#include <asm/winmacro.h> 151da177e4SLinus Torvalds#include <asm/asmmacro.h> 161da177e4SLinus Torvalds#include <asm/thread_info.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds/* WARNING: This routine is hairy and _very_ complicated, but it 191da177e4SLinus Torvalds * must be as fast as possible as it handles the allocation 201da177e4SLinus Torvalds * of register windows to the user and kernel. If you touch 211da177e4SLinus Torvalds * this code be _very_ careful as many other pieces of the 221da177e4SLinus Torvalds * kernel depend upon how this code behaves. You have been 231da177e4SLinus Torvalds * duly warned... 241da177e4SLinus Torvalds */ 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds/* We define macro's for registers which have a fixed 271da177e4SLinus Torvalds * meaning throughout this entire routine. The 'T' in 281da177e4SLinus Torvalds * the comments mean that the register can only be 291da177e4SLinus Torvalds * accessed when in the 'trap' window, 'G' means 301da177e4SLinus Torvalds * accessible in any window. Do not change these registers 311da177e4SLinus Torvalds * after they have been set, until you are ready to return 321da177e4SLinus Torvalds * from the trap. 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds#define t_psr l0 /* %psr at trap time T */ 351da177e4SLinus Torvalds#define t_pc l1 /* PC for trap return T */ 361da177e4SLinus Torvalds#define t_npc l2 /* NPC for trap return T */ 371da177e4SLinus Torvalds#define t_wim l3 /* %wim at trap time T */ 381da177e4SLinus Torvalds#define saved_g5 l5 /* Global save register T */ 391da177e4SLinus Torvalds#define saved_g6 l6 /* Global save register T */ 401da177e4SLinus Torvalds#define curptr g6 /* Gets set to 'current' then stays G */ 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds/* Now registers whose values can change within the handler. */ 431da177e4SLinus Torvalds#define twin_tmp l4 /* Temp reg, only usable in trap window T */ 441da177e4SLinus Torvalds#define glob_tmp g5 /* Global temporary reg, usable anywhere G */ 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds .text 471da177e4SLinus Torvalds .align 4 481da177e4SLinus Torvalds /* BEGINNING OF PATCH INSTRUCTIONS */ 491da177e4SLinus Torvalds /* On a 7-window Sparc the boot code patches spnwin_* 501da177e4SLinus Torvalds * instructions with the following ones. 511da177e4SLinus Torvalds */ 521da177e4SLinus Torvalds .globl spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win 531da177e4SLinus Torvaldsspnwin_patch1_7win: sll %t_wim, 6, %glob_tmp 541da177e4SLinus Torvaldsspnwin_patch2_7win: and %glob_tmp, 0x7f, %glob_tmp 551da177e4SLinus Torvaldsspnwin_patch3_7win: and %twin_tmp, 0x7f, %twin_tmp 561da177e4SLinus Torvalds /* END OF PATCH INSTRUCTIONS */ 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds /* The trap entry point has done the following: 591da177e4SLinus Torvalds * 601da177e4SLinus Torvalds * rd %psr, %l0 611da177e4SLinus Torvalds * rd %wim, %l3 621da177e4SLinus Torvalds * b spill_window_entry 631da177e4SLinus Torvalds * andcc %l0, PSR_PS, %g0 641da177e4SLinus Torvalds */ 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds /* Datum current_thread_info->uwinmask contains at all times a bitmask 671da177e4SLinus Torvalds * where if any user windows are active, at least one bit will 681da177e4SLinus Torvalds * be set in to mask. If no user windows are active, the bitmask 691da177e4SLinus Torvalds * will be all zeroes. 701da177e4SLinus Torvalds */ 711da177e4SLinus Torvalds .globl spill_window_entry 721da177e4SLinus Torvalds .globl spnwin_patch1, spnwin_patch2, spnwin_patch3 731da177e4SLinus Torvaldsspill_window_entry: 741da177e4SLinus Torvalds /* LOCATION: Trap Window */ 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds mov %g5, %saved_g5 ! save away global temp register 771da177e4SLinus Torvalds mov %g6, %saved_g6 ! save away 'current' ptr register 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds /* Compute what the new %wim will be if we save the 801da177e4SLinus Torvalds * window properly in this trap handler. 811da177e4SLinus Torvalds * 821da177e4SLinus Torvalds * newwim = ((%wim>>1) | (%wim<<(nwindows - 1))); 831da177e4SLinus Torvalds */ 841da177e4SLinus Torvalds srl %t_wim, 0x1, %twin_tmp 851da177e4SLinus Torvaldsspnwin_patch1: sll %t_wim, 7, %glob_tmp 861da177e4SLinus Torvalds or %glob_tmp, %twin_tmp, %glob_tmp 871da177e4SLinus Torvaldsspnwin_patch2: and %glob_tmp, 0xff, %glob_tmp 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds /* The trap entry point has set the condition codes 901da177e4SLinus Torvalds * up for us to see if this is from user or kernel. 911da177e4SLinus Torvalds * Get the load of 'curptr' out of the way. 921da177e4SLinus Torvalds */ 931da177e4SLinus Torvalds LOAD_CURRENT(curptr, twin_tmp) 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds andcc %t_psr, PSR_PS, %g0 961da177e4SLinus Torvalds be,a spwin_fromuser ! all user wins, branch 971da177e4SLinus Torvalds save %g0, %g0, %g0 ! Go where saving will occur 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds /* See if any user windows are active in the set. */ 1001da177e4SLinus Torvalds ld [%curptr + TI_UWINMASK], %twin_tmp ! grab win mask 1011da177e4SLinus Torvalds orcc %g0, %twin_tmp, %g0 ! check for set bits 1021da177e4SLinus Torvalds bne spwin_exist_uwins ! yep, there are some 1031da177e4SLinus Torvalds andn %twin_tmp, %glob_tmp, %twin_tmp ! compute new uwinmask 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds /* Save into the window which must be saved and do it. 1061da177e4SLinus Torvalds * Basically if we are here, this means that we trapped 1071da177e4SLinus Torvalds * from kernel mode with only kernel windows in the register 1081da177e4SLinus Torvalds * file. 1091da177e4SLinus Torvalds */ 1101da177e4SLinus Torvalds save %g0, %g0, %g0 ! save into the window to stash away 1111da177e4SLinus Torvalds wr %glob_tmp, 0x0, %wim ! set new %wim, this is safe now 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvaldsspwin_no_userwins_from_kernel: 1141da177e4SLinus Torvalds /* LOCATION: Window to be saved */ 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds STORE_WINDOW(sp) ! stash the window 1171da177e4SLinus Torvalds restore %g0, %g0, %g0 ! go back into trap window 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* LOCATION: Trap window */ 1201da177e4SLinus Torvalds mov %saved_g5, %g5 ! restore %glob_tmp 1211da177e4SLinus Torvalds mov %saved_g6, %g6 ! restore %curptr 1221da177e4SLinus Torvalds wr %t_psr, 0x0, %psr ! restore condition codes in %psr 1231da177e4SLinus Torvalds WRITE_PAUSE ! waste some time 1241da177e4SLinus Torvalds jmp %t_pc ! Return from trap 1251da177e4SLinus Torvalds rett %t_npc ! we are done 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvaldsspwin_exist_uwins: 1281da177e4SLinus Torvalds /* LOCATION: Trap window */ 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds /* Wow, user windows have to be dealt with, this is dirty 1311da177e4SLinus Torvalds * and messy as all hell. And difficult to follow if you 1321da177e4SLinus Torvalds * are approaching the infamous register window trap handling 1331da177e4SLinus Torvalds * problem for the first time. DON'T LOOK! 1341da177e4SLinus Torvalds * 1351da177e4SLinus Torvalds * Note that how the execution path works out, the new %wim 1361da177e4SLinus Torvalds * will be left for us in the global temporary register, 1371da177e4SLinus Torvalds * %glob_tmp. We cannot set the new %wim first because we 1381da177e4SLinus Torvalds * need to save into the appropriate window without inducing 1391da177e4SLinus Torvalds * a trap (traps are off, we'd get a watchdog wheee)... 1401da177e4SLinus Torvalds * But first, store the new user window mask calculated 1411da177e4SLinus Torvalds * above. 1421da177e4SLinus Torvalds */ 1431da177e4SLinus Torvalds st %twin_tmp, [%curptr + TI_UWINMASK] 1441da177e4SLinus Torvalds save %g0, %g0, %g0 ! Go to where the saving will occur 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvaldsspwin_fromuser: 1471da177e4SLinus Torvalds /* LOCATION: Window to be saved */ 1481da177e4SLinus Torvalds wr %glob_tmp, 0x0, %wim ! Now it is safe to set new %wim 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds /* LOCATION: Window to be saved */ 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds /* This instruction branches to a routine which will check 1531da177e4SLinus Torvalds * to validity of the users stack pointer by whatever means 1541da177e4SLinus Torvalds * are necessary. This means that this is architecture 1551da177e4SLinus Torvalds * specific and thus this branch instruction will need to 1561da177e4SLinus Torvalds * be patched at boot time once the machine type is known. 1571da177e4SLinus Torvalds * This routine _shall not_ touch %curptr under any 1581da177e4SLinus Torvalds * circumstances whatsoever! It will branch back to the 1591da177e4SLinus Torvalds * label 'spwin_good_ustack' if the stack is ok but still 1601da177e4SLinus Torvalds * needs to be dumped (SRMMU for instance will not need to 1611da177e4SLinus Torvalds * do this) or 'spwin_finish_up' if the stack is ok and the 1621da177e4SLinus Torvalds * registers have already been saved. If the stack is found 1631da177e4SLinus Torvalds * to be bogus for some reason the routine shall branch to 1641da177e4SLinus Torvalds * the label 'spwin_user_stack_is_bolixed' which will take 1651da177e4SLinus Torvalds * care of things at that point. 1661da177e4SLinus Torvalds */ 167054768a1SSam Ravnborg b spwin_srmmu_stackchk 1681da177e4SLinus Torvalds andcc %sp, 0x7, %g0 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvaldsspwin_good_ustack: 1711da177e4SLinus Torvalds /* LOCATION: Window to be saved */ 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /* The users stack is ok and we can safely save it at 1741da177e4SLinus Torvalds * %sp. 1751da177e4SLinus Torvalds */ 1761da177e4SLinus Torvalds STORE_WINDOW(sp) 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvaldsspwin_finish_up: 1791da177e4SLinus Torvalds restore %g0, %g0, %g0 /* Back to trap window. */ 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds /* LOCATION: Trap window */ 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds /* We have spilled successfully, and we have properly stored 1841da177e4SLinus Torvalds * the appropriate window onto the stack. 1851da177e4SLinus Torvalds */ 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds /* Restore saved globals */ 1881da177e4SLinus Torvalds mov %saved_g5, %g5 1891da177e4SLinus Torvalds mov %saved_g6, %g6 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds wr %t_psr, 0x0, %psr 1921da177e4SLinus Torvalds WRITE_PAUSE 1931da177e4SLinus Torvalds jmp %t_pc 1941da177e4SLinus Torvalds rett %t_npc 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvaldsspwin_user_stack_is_bolixed: 1971da177e4SLinus Torvalds /* LOCATION: Window to be saved */ 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* Wheee, user has trashed his/her stack. We have to decide 2001da177e4SLinus Torvalds * how to proceed based upon whether we came from kernel mode 2011da177e4SLinus Torvalds * or not. If we came from kernel mode, toss the window into 2021da177e4SLinus Torvalds * a special buffer and proceed, the kernel _needs_ a window 2031da177e4SLinus Torvalds * and we could be in an interrupt handler so timing is crucial. 2041da177e4SLinus Torvalds * If we came from user land we build a full stack frame and call 2051da177e4SLinus Torvalds * c-code to gun down the process. 2061da177e4SLinus Torvalds */ 2071da177e4SLinus Torvalds rd %psr, %glob_tmp 2081da177e4SLinus Torvalds andcc %glob_tmp, PSR_PS, %g0 2091da177e4SLinus Torvalds bne spwin_bad_ustack_from_kernel 2101da177e4SLinus Torvalds nop 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds /* Oh well, throw this one window into the per-task window 2131da177e4SLinus Torvalds * buffer, the first one. 2141da177e4SLinus Torvalds */ 2151da177e4SLinus Torvalds st %sp, [%curptr + TI_RWIN_SPTRS] 2161da177e4SLinus Torvalds STORE_WINDOW(curptr + TI_REG_WINDOW) 2171da177e4SLinus Torvalds restore %g0, %g0, %g0 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds /* LOCATION: Trap Window */ 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds /* Back in the trap window, update winbuffer save count. */ 2221da177e4SLinus Torvalds mov 1, %twin_tmp 2231da177e4SLinus Torvalds st %twin_tmp, [%curptr + TI_W_SAVED] 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds /* Compute new user window mask. What we are basically 2261da177e4SLinus Torvalds * doing is taking two windows, the invalid one at trap 2271da177e4SLinus Torvalds * time and the one we attempted to throw onto the users 2281da177e4SLinus Torvalds * stack, and saying that everything else is an ok user 2291da177e4SLinus Torvalds * window. umask = ((~(%t_wim | %wim)) & valid_wim_bits) 2301da177e4SLinus Torvalds */ 2311da177e4SLinus Torvalds rd %wim, %twin_tmp 2321da177e4SLinus Torvalds or %twin_tmp, %t_wim, %twin_tmp 2331da177e4SLinus Torvalds not %twin_tmp 2341da177e4SLinus Torvaldsspnwin_patch3: and %twin_tmp, 0xff, %twin_tmp ! patched on 7win Sparcs 2351da177e4SLinus Torvalds st %twin_tmp, [%curptr + TI_UWINMASK] 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ) 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds sethi %hi(STACK_OFFSET), %sp 2401da177e4SLinus Torvalds or %sp, %lo(STACK_OFFSET), %sp 2411da177e4SLinus Torvalds add %curptr, %sp, %sp 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds /* Restore the saved globals and build a pt_regs frame. */ 2441da177e4SLinus Torvalds mov %saved_g5, %g5 2451da177e4SLinus Torvalds mov %saved_g6, %g6 2461da177e4SLinus Torvalds STORE_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds sethi %hi(STACK_OFFSET), %g6 2491da177e4SLinus Torvalds or %g6, %lo(STACK_OFFSET), %g6 2501da177e4SLinus Torvalds sub %sp, %g6, %g6 ! curptr 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds /* Turn on traps and call c-code to deal with it. */ 2531da177e4SLinus Torvalds wr %t_psr, PSR_ET, %psr 2541da177e4SLinus Torvalds nop 2551da177e4SLinus Torvalds call window_overflow_fault 2561da177e4SLinus Torvalds nop 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds /* Return from trap if C-code actually fixes things, if it 2591da177e4SLinus Torvalds * doesn't then we never get this far as the process will 2601da177e4SLinus Torvalds * be given the look of death from Commander Peanut. 2611da177e4SLinus Torvalds */ 2621da177e4SLinus Torvalds b ret_trap_entry 2631da177e4SLinus Torvalds clr %l6 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvaldsspwin_bad_ustack_from_kernel: 2661da177e4SLinus Torvalds /* LOCATION: Window to be saved */ 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds /* The kernel provoked a spill window trap, but the window we 2691da177e4SLinus Torvalds * need to save is a user one and the process has trashed its 2701da177e4SLinus Torvalds * stack pointer. We need to be quick, so we throw it into 2711da177e4SLinus Torvalds * a per-process window buffer until we can properly handle 2721da177e4SLinus Torvalds * this later on. 2731da177e4SLinus Torvalds */ 2741da177e4SLinus Torvalds SAVE_BOLIXED_USER_STACK(curptr, glob_tmp) 2751da177e4SLinus Torvalds restore %g0, %g0, %g0 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds /* LOCATION: Trap window */ 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds /* Restore globals, condition codes in the %psr and 2801da177e4SLinus Torvalds * return from trap. Note, restoring %g6 when returning 2811da177e4SLinus Torvalds * to kernel mode is not necessarily these days. ;-) 2821da177e4SLinus Torvalds */ 2831da177e4SLinus Torvalds mov %saved_g5, %g5 2841da177e4SLinus Torvalds mov %saved_g6, %g6 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds wr %t_psr, 0x0, %psr 2871da177e4SLinus Torvalds WRITE_PAUSE 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds jmp %t_pc 2901da177e4SLinus Torvalds rett %t_npc 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds/* Undefine the register macros which would only cause trouble 2931da177e4SLinus Torvalds * if used below. This helps find 'stupid' coding errors that 2941da177e4SLinus Torvalds * produce 'odd' behavior. The routines below are allowed to 2951da177e4SLinus Torvalds * make usage of glob_tmp and t_psr so we leave them defined. 2961da177e4SLinus Torvalds */ 2971da177e4SLinus Torvalds#undef twin_tmp 2981da177e4SLinus Torvalds#undef curptr 2991da177e4SLinus Torvalds#undef t_pc 3001da177e4SLinus Torvalds#undef t_npc 3011da177e4SLinus Torvalds#undef t_wim 3021da177e4SLinus Torvalds#undef saved_g5 3031da177e4SLinus Torvalds#undef saved_g6 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds/* Now come the per-architecture window overflow stack checking routines. 3061da177e4SLinus Torvalds * As noted above %curptr cannot be touched by this routine at all. 3071da177e4SLinus Torvalds */ 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds /* This is a generic SRMMU routine. As far as I know this 3101da177e4SLinus Torvalds * works for all current v8/srmmu implementations, we'll 3111da177e4SLinus Torvalds * see... 3121da177e4SLinus Torvalds */ 3131da177e4SLinus Torvalds .globl spwin_srmmu_stackchk 3141da177e4SLinus Torvaldsspwin_srmmu_stackchk: 3151da177e4SLinus Torvalds /* LOCATION: Window to be saved on the stack */ 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* Because of SMP concerns and speed we play a trick. 3181da177e4SLinus Torvalds * We disable fault traps in the MMU control register, 3191da177e4SLinus Torvalds * Execute the stores, then check the fault registers 3201da177e4SLinus Torvalds * to see what happens. I can hear Linus now 3211da177e4SLinus Torvalds * "disgusting... broken hardware...". 3221da177e4SLinus Torvalds * 3231da177e4SLinus Torvalds * But first, check to see if the users stack has ended 3241da177e4SLinus Torvalds * up in kernel vma, then we would succeed for the 'wrong' 3251da177e4SLinus Torvalds * reason... ;( Note that the 'sethi' below assumes the 3261da177e4SLinus Torvalds * kernel is page aligned, which should always be the case. 3271da177e4SLinus Torvalds */ 3281da177e4SLinus Torvalds /* Check results of callers andcc %sp, 0x7, %g0 */ 3291da177e4SLinus Torvalds bne spwin_user_stack_is_bolixed 3301da177e4SLinus Torvalds sethi %hi(PAGE_OFFSET), %glob_tmp 3311da177e4SLinus Torvalds cmp %glob_tmp, %sp 3321da177e4SLinus Torvalds bleu spwin_user_stack_is_bolixed 3331da177e4SLinus Torvalds mov AC_M_SFSR, %glob_tmp 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds /* Clear the fault status and turn on the no_fault bit. */ 3361ec8cf62SSam RavnborgLEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %g0) ! eat SFSR 3371ec8cf62SSam RavnborgSUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %g0) ! eat SFSR 3381da177e4SLinus Torvalds 3391ec8cf62SSam RavnborgLEON_PI(lda [%g0] ASI_LEON_MMUREGS, %glob_tmp) ! read MMU control 3401ec8cf62SSam RavnborgSUN_PI_(lda [%g0] ASI_M_MMUREGS, %glob_tmp) ! read MMU control 3411da177e4SLinus Torvalds or %glob_tmp, 0x2, %glob_tmp ! or in no_fault bit 3421ec8cf62SSam RavnborgLEON_PI(sta %glob_tmp, [%g0] ASI_LEON_MMUREGS) ! set it 3431ec8cf62SSam RavnborgSUN_PI_(sta %glob_tmp, [%g0] ASI_M_MMUREGS) ! set it 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds /* Dump the registers and cross fingers. */ 3461da177e4SLinus Torvalds STORE_WINDOW(sp) 3471da177e4SLinus Torvalds 3481da177e4SLinus Torvalds /* Clear the no_fault bit and check the status. */ 3491da177e4SLinus Torvalds andn %glob_tmp, 0x2, %glob_tmp 3501ec8cf62SSam RavnborgLEON_PI(sta %glob_tmp, [%g0] ASI_LEON_MMUREGS) 3511ec8cf62SSam RavnborgSUN_PI_(sta %glob_tmp, [%g0] ASI_M_MMUREGS) 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds mov AC_M_SFAR, %glob_tmp 3541ec8cf62SSam RavnborgLEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %g0) 3551ec8cf62SSam RavnborgSUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %g0) 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds mov AC_M_SFSR, %glob_tmp 3581ec8cf62SSam RavnborgLEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %glob_tmp) 3591ec8cf62SSam RavnborgSUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %glob_tmp) 3601da177e4SLinus Torvalds andcc %glob_tmp, 0x2, %g0 ! did we fault? 3611da177e4SLinus Torvalds be,a spwin_finish_up + 0x4 ! cool beans, success 3621da177e4SLinus Torvalds restore %g0, %g0, %g0 3631da177e4SLinus Torvalds 3641da177e4SLinus Torvalds rd %psr, %glob_tmp 3651da177e4SLinus Torvalds b spwin_user_stack_is_bolixed + 0x4 ! we faulted, ugh 3661da177e4SLinus Torvalds nop 367