1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 2d670bd4fSSam Ravnborg/* 3d670bd4fSSam Ravnborg * rtrap.S: Return from Sparc trap low-level code. 4d670bd4fSSam Ravnborg * 5d670bd4fSSam Ravnborg * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6d670bd4fSSam Ravnborg */ 7d670bd4fSSam Ravnborg 8d670bd4fSSam Ravnborg#include <asm/page.h> 9d670bd4fSSam Ravnborg#include <asm/ptrace.h> 10d670bd4fSSam Ravnborg#include <asm/psr.h> 11d670bd4fSSam Ravnborg#include <asm/asi.h> 12d670bd4fSSam Ravnborg#include <asm/smp.h> 13d670bd4fSSam Ravnborg#include <asm/contregs.h> 14d670bd4fSSam Ravnborg#include <asm/winmacro.h> 15d670bd4fSSam Ravnborg#include <asm/asmmacro.h> 16d670bd4fSSam Ravnborg#include <asm/thread_info.h> 17d670bd4fSSam Ravnborg 18d670bd4fSSam Ravnborg#define t_psr l0 19d670bd4fSSam Ravnborg#define t_pc l1 20d670bd4fSSam Ravnborg#define t_npc l2 21d670bd4fSSam Ravnborg#define t_wim l3 22d670bd4fSSam Ravnborg#define twin_tmp1 l4 23d670bd4fSSam Ravnborg#define glob_tmp g4 24d670bd4fSSam Ravnborg#define curptr g6 25d670bd4fSSam Ravnborg 26d670bd4fSSam Ravnborg /* 7 WINDOW SPARC PATCH INSTRUCTIONS */ 27d670bd4fSSam Ravnborg .globl rtrap_7win_patch1, rtrap_7win_patch2, rtrap_7win_patch3 28d670bd4fSSam Ravnborg .globl rtrap_7win_patch4, rtrap_7win_patch5 29d670bd4fSSam Ravnborgrtrap_7win_patch1: srl %t_wim, 0x6, %glob_tmp 30d670bd4fSSam Ravnborgrtrap_7win_patch2: and %glob_tmp, 0x7f, %glob_tmp 31d670bd4fSSam Ravnborgrtrap_7win_patch3: srl %g1, 7, %g2 32d670bd4fSSam Ravnborgrtrap_7win_patch4: srl %g2, 6, %g2 33d670bd4fSSam Ravnborgrtrap_7win_patch5: and %g1, 0x7f, %g1 34d670bd4fSSam Ravnborg /* END OF PATCH INSTRUCTIONS */ 35d670bd4fSSam Ravnborg 36d670bd4fSSam Ravnborg /* We need to check for a few things which are: 37d670bd4fSSam Ravnborg * 1) The need to call schedule() because this 38d670bd4fSSam Ravnborg * processes quantum is up. 39d670bd4fSSam Ravnborg * 2) Pending signals for this process, if any 40d670bd4fSSam Ravnborg * exist we need to call do_signal() to do 41d670bd4fSSam Ravnborg * the needy. 42d670bd4fSSam Ravnborg * 43d670bd4fSSam Ravnborg * Else we just check if the rett would land us 44d670bd4fSSam Ravnborg * in an invalid window, if so we need to grab 45d670bd4fSSam Ravnborg * it off the user/kernel stack first. 46d670bd4fSSam Ravnborg */ 47d670bd4fSSam Ravnborg 48d670bd4fSSam Ravnborg .globl ret_trap_entry, rtrap_patch1, rtrap_patch2 49d670bd4fSSam Ravnborg .globl rtrap_patch3, rtrap_patch4, rtrap_patch5 50d670bd4fSSam Ravnborg .globl ret_trap_lockless_ipi 51d670bd4fSSam Ravnborgret_trap_entry: 52d670bd4fSSam Ravnborgret_trap_lockless_ipi: 53d670bd4fSSam Ravnborg andcc %t_psr, PSR_PS, %g0 54d670bd4fSSam Ravnborg sethi %hi(PSR_SYSCALL), %g1 55d670bd4fSSam Ravnborg be 1f 56d670bd4fSSam Ravnborg andn %t_psr, %g1, %t_psr 57d670bd4fSSam Ravnborg 58d670bd4fSSam Ravnborg wr %t_psr, 0x0, %psr 59d670bd4fSSam Ravnborg b ret_trap_kernel 60d670bd4fSSam Ravnborg nop 61d670bd4fSSam Ravnborg 62d670bd4fSSam Ravnborg1: 63d670bd4fSSam Ravnborg ld [%curptr + TI_FLAGS], %g2 64d670bd4fSSam Ravnborg andcc %g2, (_TIF_NEED_RESCHED), %g0 65d670bd4fSSam Ravnborg be signal_p 66d670bd4fSSam Ravnborg nop 67d670bd4fSSam Ravnborg 68d670bd4fSSam Ravnborg call schedule 69d670bd4fSSam Ravnborg nop 70d670bd4fSSam Ravnborg 71d670bd4fSSam Ravnborg ld [%curptr + TI_FLAGS], %g2 72d670bd4fSSam Ravnborgsignal_p: 73d670bd4fSSam Ravnborg andcc %g2, _TIF_DO_NOTIFY_RESUME_MASK, %g0 74d670bd4fSSam Ravnborg bz,a ret_trap_continue 75d670bd4fSSam Ravnborg ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 76d670bd4fSSam Ravnborg 77d670bd4fSSam Ravnborg mov %g2, %o2 78*c599a782SAndreas Larsson mov %l6, %o1 79d670bd4fSSam Ravnborg call do_notify_resume 80d670bd4fSSam Ravnborg add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr 81d670bd4fSSam Ravnborg 82caebf910SAl Viro b signal_p 83caebf910SAl Viro ld [%curptr + TI_FLAGS], %g2 84caebf910SAl Viro 85d670bd4fSSam Ravnborgret_trap_continue: 86d670bd4fSSam Ravnborg sethi %hi(PSR_SYSCALL), %g1 87d670bd4fSSam Ravnborg andn %t_psr, %g1, %t_psr 88d670bd4fSSam Ravnborg wr %t_psr, 0x0, %psr 89d670bd4fSSam Ravnborg WRITE_PAUSE 90d670bd4fSSam Ravnborg 91d670bd4fSSam Ravnborg ld [%curptr + TI_W_SAVED], %twin_tmp1 92d670bd4fSSam Ravnborg orcc %g0, %twin_tmp1, %g0 93d670bd4fSSam Ravnborg be ret_trap_nobufwins 94d670bd4fSSam Ravnborg nop 95d670bd4fSSam Ravnborg 96d670bd4fSSam Ravnborg wr %t_psr, PSR_ET, %psr 97d670bd4fSSam Ravnborg WRITE_PAUSE 98d670bd4fSSam Ravnborg 99d670bd4fSSam Ravnborg mov 1, %o1 100d670bd4fSSam Ravnborg call try_to_clear_window_buffer 101d670bd4fSSam Ravnborg add %sp, STACKFRAME_SZ, %o0 102d670bd4fSSam Ravnborg 103d670bd4fSSam Ravnborg b signal_p 104d670bd4fSSam Ravnborg ld [%curptr + TI_FLAGS], %g2 105d670bd4fSSam Ravnborg 106d670bd4fSSam Ravnborgret_trap_nobufwins: 107d670bd4fSSam Ravnborg /* Load up the user's out registers so we can pull 108d670bd4fSSam Ravnborg * a window from the stack, if necessary. 109d670bd4fSSam Ravnborg */ 110d670bd4fSSam Ravnborg LOAD_PT_INS(sp) 111d670bd4fSSam Ravnborg 112d670bd4fSSam Ravnborg /* If there are already live user windows in the 113d670bd4fSSam Ravnborg * set we can return from trap safely. 114d670bd4fSSam Ravnborg */ 115d670bd4fSSam Ravnborg ld [%curptr + TI_UWINMASK], %twin_tmp1 116d670bd4fSSam Ravnborg orcc %g0, %twin_tmp1, %g0 117d670bd4fSSam Ravnborg bne ret_trap_userwins_ok 118d670bd4fSSam Ravnborg nop 119d670bd4fSSam Ravnborg 120d670bd4fSSam Ravnborg /* Calculate new %wim, we have to pull a register 121d670bd4fSSam Ravnborg * window from the users stack. 122d670bd4fSSam Ravnborg */ 123d670bd4fSSam Ravnborgret_trap_pull_one_window: 124d670bd4fSSam Ravnborg rd %wim, %t_wim 125d670bd4fSSam Ravnborg sll %t_wim, 0x1, %twin_tmp1 126d670bd4fSSam Ravnborgrtrap_patch1: srl %t_wim, 0x7, %glob_tmp 127d670bd4fSSam Ravnborg or %glob_tmp, %twin_tmp1, %glob_tmp 128d670bd4fSSam Ravnborgrtrap_patch2: and %glob_tmp, 0xff, %glob_tmp 129d670bd4fSSam Ravnborg 130d670bd4fSSam Ravnborg wr %glob_tmp, 0x0, %wim 131d670bd4fSSam Ravnborg 132d670bd4fSSam Ravnborg /* Here comes the architecture specific 133d670bd4fSSam Ravnborg * branch to the user stack checking routine 134d670bd4fSSam Ravnborg * for return from traps. 135d670bd4fSSam Ravnborg */ 136ef136bc9SSam Ravnborg b srmmu_rett_stackchk 137d670bd4fSSam Ravnborg andcc %fp, 0x7, %g0 138d670bd4fSSam Ravnborg 139d670bd4fSSam Ravnborgret_trap_userwins_ok: 140d670bd4fSSam Ravnborg LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) 141d670bd4fSSam Ravnborg or %t_pc, %t_npc, %g2 142d670bd4fSSam Ravnborg andcc %g2, 0x3, %g0 143d670bd4fSSam Ravnborg sethi %hi(PSR_SYSCALL), %g2 144d670bd4fSSam Ravnborg be 1f 145d670bd4fSSam Ravnborg andn %t_psr, %g2, %t_psr 146d670bd4fSSam Ravnborg 147d670bd4fSSam Ravnborg b ret_trap_unaligned_pc 148d670bd4fSSam Ravnborg add %sp, STACKFRAME_SZ, %o0 149d670bd4fSSam Ravnborg 150d670bd4fSSam Ravnborg1: 151d670bd4fSSam Ravnborg LOAD_PT_YREG(sp, g1) 152d670bd4fSSam Ravnborg LOAD_PT_GLOBALS(sp) 153d670bd4fSSam Ravnborg 154d670bd4fSSam Ravnborg wr %t_psr, 0x0, %psr 155d670bd4fSSam Ravnborg WRITE_PAUSE 156d670bd4fSSam Ravnborg 157d670bd4fSSam Ravnborg jmp %t_pc 158d670bd4fSSam Ravnborg rett %t_npc 159d670bd4fSSam Ravnborg 160d670bd4fSSam Ravnborgret_trap_unaligned_pc: 161d670bd4fSSam Ravnborg ld [%sp + STACKFRAME_SZ + PT_PC], %o1 162d670bd4fSSam Ravnborg ld [%sp + STACKFRAME_SZ + PT_NPC], %o2 163d670bd4fSSam Ravnborg ld [%sp + STACKFRAME_SZ + PT_PSR], %o3 164d670bd4fSSam Ravnborg 165d670bd4fSSam Ravnborg wr %t_wim, 0x0, %wim ! or else... 166d670bd4fSSam Ravnborg 167d670bd4fSSam Ravnborg wr %t_psr, PSR_ET, %psr 168d670bd4fSSam Ravnborg WRITE_PAUSE 169d670bd4fSSam Ravnborg 170d670bd4fSSam Ravnborg call do_memaccess_unaligned 171d670bd4fSSam Ravnborg nop 172d670bd4fSSam Ravnborg 173d670bd4fSSam Ravnborg b signal_p 174d670bd4fSSam Ravnborg ld [%curptr + TI_FLAGS], %g2 175d670bd4fSSam Ravnborg 176d670bd4fSSam Ravnborgret_trap_kernel: 177d670bd4fSSam Ravnborg /* Will the rett land us in the invalid window? */ 178d670bd4fSSam Ravnborg mov 2, %g1 179d670bd4fSSam Ravnborg sll %g1, %t_psr, %g1 180d670bd4fSSam Ravnborgrtrap_patch3: srl %g1, 8, %g2 181d670bd4fSSam Ravnborg or %g1, %g2, %g1 182d670bd4fSSam Ravnborg rd %wim, %g2 183d670bd4fSSam Ravnborg andcc %g2, %g1, %g0 184d670bd4fSSam Ravnborg be 1f ! Nope, just return from the trap 185d670bd4fSSam Ravnborg sll %g2, 0x1, %g1 186d670bd4fSSam Ravnborg 187d670bd4fSSam Ravnborg /* We have to grab a window before returning. */ 188d670bd4fSSam Ravnborgrtrap_patch4: srl %g2, 7, %g2 189d670bd4fSSam Ravnborg or %g1, %g2, %g1 190d670bd4fSSam Ravnborgrtrap_patch5: and %g1, 0xff, %g1 191d670bd4fSSam Ravnborg 192d670bd4fSSam Ravnborg wr %g1, 0x0, %wim 193d670bd4fSSam Ravnborg 194d670bd4fSSam Ravnborg /* Grrr, make sure we load from the right %sp... */ 195d670bd4fSSam Ravnborg LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 196d670bd4fSSam Ravnborg 197d670bd4fSSam Ravnborg restore %g0, %g0, %g0 198d670bd4fSSam Ravnborg LOAD_WINDOW(sp) 199d670bd4fSSam Ravnborg b 2f 200d670bd4fSSam Ravnborg save %g0, %g0, %g0 201d670bd4fSSam Ravnborg 202d670bd4fSSam Ravnborg /* Reload the entire frame in case this is from a 203d670bd4fSSam Ravnborg * kernel system call or whatever... 204d670bd4fSSam Ravnborg */ 205d670bd4fSSam Ravnborg1: 206d670bd4fSSam Ravnborg LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 207d670bd4fSSam Ravnborg2: 208d670bd4fSSam Ravnborg sethi %hi(PSR_SYSCALL), %twin_tmp1 209d670bd4fSSam Ravnborg andn %t_psr, %twin_tmp1, %t_psr 210d670bd4fSSam Ravnborg wr %t_psr, 0x0, %psr 211d670bd4fSSam Ravnborg WRITE_PAUSE 212d670bd4fSSam Ravnborg 213d670bd4fSSam Ravnborg jmp %t_pc 214d670bd4fSSam Ravnborg rett %t_npc 215d670bd4fSSam Ravnborg 216d670bd4fSSam Ravnborgret_trap_user_stack_is_bolixed: 217d670bd4fSSam Ravnborg wr %t_wim, 0x0, %wim 218d670bd4fSSam Ravnborg 219d670bd4fSSam Ravnborg wr %t_psr, PSR_ET, %psr 220d670bd4fSSam Ravnborg WRITE_PAUSE 221d670bd4fSSam Ravnborg 222d670bd4fSSam Ravnborg call window_ret_fault 223d670bd4fSSam Ravnborg add %sp, STACKFRAME_SZ, %o0 224d670bd4fSSam Ravnborg 225d670bd4fSSam Ravnborg b signal_p 226d670bd4fSSam Ravnborg ld [%curptr + TI_FLAGS], %g2 227d670bd4fSSam Ravnborg 228d670bd4fSSam Ravnborg .globl srmmu_rett_stackchk 229d670bd4fSSam Ravnborgsrmmu_rett_stackchk: 230d670bd4fSSam Ravnborg bne ret_trap_user_stack_is_bolixed 231d670bd4fSSam Ravnborg sethi %hi(PAGE_OFFSET), %g1 232d670bd4fSSam Ravnborg cmp %g1, %fp 233d670bd4fSSam Ravnborg bleu ret_trap_user_stack_is_bolixed 234d670bd4fSSam Ravnborg mov AC_M_SFSR, %g1 2351ec8cf62SSam RavnborgLEON_PI(lda [%g1] ASI_LEON_MMUREGS, %g0) 2361ec8cf62SSam RavnborgSUN_PI_(lda [%g1] ASI_M_MMUREGS, %g0) 237d670bd4fSSam Ravnborg 2381ec8cf62SSam RavnborgLEON_PI(lda [%g0] ASI_LEON_MMUREGS, %g1) 2391ec8cf62SSam RavnborgSUN_PI_(lda [%g0] ASI_M_MMUREGS, %g1) 240d670bd4fSSam Ravnborg or %g1, 0x2, %g1 2411ec8cf62SSam RavnborgLEON_PI(sta %g1, [%g0] ASI_LEON_MMUREGS) 2421ec8cf62SSam RavnborgSUN_PI_(sta %g1, [%g0] ASI_M_MMUREGS) 243d670bd4fSSam Ravnborg 244d670bd4fSSam Ravnborg restore %g0, %g0, %g0 245d670bd4fSSam Ravnborg 246d670bd4fSSam Ravnborg LOAD_WINDOW(sp) 247d670bd4fSSam Ravnborg 248d670bd4fSSam Ravnborg save %g0, %g0, %g0 249d670bd4fSSam Ravnborg 250d670bd4fSSam Ravnborg andn %g1, 0x2, %g1 2511ec8cf62SSam RavnborgLEON_PI(sta %g1, [%g0] ASI_LEON_MMUREGS) 2521ec8cf62SSam RavnborgSUN_PI_(sta %g1, [%g0] ASI_M_MMUREGS) 253d670bd4fSSam Ravnborg 254d670bd4fSSam Ravnborg mov AC_M_SFAR, %g2 2551ec8cf62SSam RavnborgLEON_PI(lda [%g2] ASI_LEON_MMUREGS, %g2) 2561ec8cf62SSam RavnborgSUN_PI_(lda [%g2] ASI_M_MMUREGS, %g2) 257d670bd4fSSam Ravnborg 258d670bd4fSSam Ravnborg mov AC_M_SFSR, %g1 2591ec8cf62SSam RavnborgLEON_PI(lda [%g1] ASI_LEON_MMUREGS, %g1) 2601ec8cf62SSam RavnborgSUN_PI_(lda [%g1] ASI_M_MMUREGS, %g1) 261d670bd4fSSam Ravnborg andcc %g1, 0x2, %g0 262d670bd4fSSam Ravnborg be ret_trap_userwins_ok 263d670bd4fSSam Ravnborg nop 264d670bd4fSSam Ravnborg 265d670bd4fSSam Ravnborg b,a ret_trap_user_stack_is_bolixed 266