17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 541f63f87Spetede * Common Development and Distribution License (the "License"). 641f63f87Spetede * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22b9e93c10SJonathan Haslam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate#if !defined(lint) 277c478bd9Sstevel@tonic-gate#include "assym.h" 287c478bd9Sstevel@tonic-gate#endif /* !lint */ 297c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 307c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 317c478bd9Sstevel@tonic-gate#include <sys/sun4asi.h> 3225cf1a30Sjl139090#include <sys/spitregs.h> 337c478bd9Sstevel@tonic-gate#include <sys/cheetahregs.h> 347c478bd9Sstevel@tonic-gate#include <sys/machtrap.h> 357c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 369acbbeafSnn35248#include <sys/machbrand.h> 377c478bd9Sstevel@tonic-gate#include <sys/pcb.h> 387c478bd9Sstevel@tonic-gate#include <sys/pte.h> 397c478bd9Sstevel@tonic-gate#include <sys/mmu.h> 407c478bd9Sstevel@tonic-gate#include <sys/machpcb.h> 417c478bd9Sstevel@tonic-gate#include <sys/async.h> 427c478bd9Sstevel@tonic-gate#include <sys/intreg.h> 437c478bd9Sstevel@tonic-gate#include <sys/scb.h> 447c478bd9Sstevel@tonic-gate#include <sys/psr_compat.h> 457c478bd9Sstevel@tonic-gate#include <sys/syscall.h> 467c478bd9Sstevel@tonic-gate#include <sys/machparam.h> 477c478bd9Sstevel@tonic-gate#include <sys/traptrace.h> 487c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 497c478bd9Sstevel@tonic-gate#include <sys/archsystm.h> 507c478bd9Sstevel@tonic-gate#include <sys/utrap.h> 517c478bd9Sstevel@tonic-gate#include <sys/clock.h> 527c478bd9Sstevel@tonic-gate#include <sys/intr.h> 537c478bd9Sstevel@tonic-gate#include <sys/fpu/fpu_simulator.h> 547c478bd9Sstevel@tonic-gate#include <vm/seg_spt.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate/* 577c478bd9Sstevel@tonic-gate * WARNING: If you add a fast trap handler which can be invoked by a 587c478bd9Sstevel@tonic-gate * non-privileged user, you may have to use the FAST_TRAP_DONE macro 597c478bd9Sstevel@tonic-gate * instead of "done" instruction to return back to the user mode. See 607c478bd9Sstevel@tonic-gate * comments for the "fast_trap_done" entry point for more information. 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the 637c478bd9Sstevel@tonic-gate * cases where you always want to process any pending interrupts before 647c478bd9Sstevel@tonic-gate * returning back to the user mode. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate#define FAST_TRAP_DONE \ 677c478bd9Sstevel@tonic-gate ba,a fast_trap_done 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate#define FAST_TRAP_DONE_CHK_INTR \ 707c478bd9Sstevel@tonic-gate ba,a fast_trap_done_chk_intr 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate/* 737c478bd9Sstevel@tonic-gate * SPARC V9 Trap Table 747c478bd9Sstevel@tonic-gate * 757c478bd9Sstevel@tonic-gate * Most of the trap handlers are made from common building 767c478bd9Sstevel@tonic-gate * blocks, and some are instantiated multiple times within 777c478bd9Sstevel@tonic-gate * the trap table. So, I build a bunch of macros, then 787c478bd9Sstevel@tonic-gate * populate the table using only the macros. 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * Many macros branch to sys_trap. Its calling convention is: 817c478bd9Sstevel@tonic-gate * %g1 kernel trap handler 827c478bd9Sstevel@tonic-gate * %g2, %g3 args for above 837c478bd9Sstevel@tonic-gate * %g4 desire %pil 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate/* 897c478bd9Sstevel@tonic-gate * Tracing macro. Adds two instructions if TRAPTRACE is defined. 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate#define TT_TRACE(label) \ 927c478bd9Sstevel@tonic-gate ba label ;\ 937c478bd9Sstevel@tonic-gate rd %pc, %g7 947c478bd9Sstevel@tonic-gate#define TT_TRACE_INS 2 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate#define TT_TRACE_L(label) \ 977c478bd9Sstevel@tonic-gate ba label ;\ 987c478bd9Sstevel@tonic-gate rd %pc, %l4 ;\ 997c478bd9Sstevel@tonic-gate clr %l4 1007c478bd9Sstevel@tonic-gate#define TT_TRACE_L_INS 3 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate#else 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate#define TT_TRACE(label) 1057c478bd9Sstevel@tonic-gate#define TT_TRACE_INS 0 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate#define TT_TRACE_L(label) 1087c478bd9Sstevel@tonic-gate#define TT_TRACE_L_INS 0 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate#endif 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate/* 1137c478bd9Sstevel@tonic-gate * This first set are funneled to trap() with %tt as the type. 1147c478bd9Sstevel@tonic-gate * Trap will then either panic or send the user a signal. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate/* 1177c478bd9Sstevel@tonic-gate * NOT is used for traps that just shouldn't happen. 1187c478bd9Sstevel@tonic-gate * It comes in both single and quadruple flavors. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate#if !defined(lint) 1217c478bd9Sstevel@tonic-gate .global trap 1227c478bd9Sstevel@tonic-gate#endif /* !lint */ 1237c478bd9Sstevel@tonic-gate#define NOT \ 1247c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1257c478bd9Sstevel@tonic-gate set trap, %g1 ;\ 1267c478bd9Sstevel@tonic-gate rdpr %tt, %g3 ;\ 1277c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1287c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1297c478bd9Sstevel@tonic-gate .align 32 1307c478bd9Sstevel@tonic-gate#define NOT4 NOT; NOT; NOT; NOT 1317c478bd9Sstevel@tonic-gate/* 1327c478bd9Sstevel@tonic-gate * RED is for traps that use the red mode handler. 1337c478bd9Sstevel@tonic-gate * We should never see these either. 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate#define RED NOT 1367c478bd9Sstevel@tonic-gate/* 1377c478bd9Sstevel@tonic-gate * BAD is used for trap vectors we don't have a kernel 1387c478bd9Sstevel@tonic-gate * handler for. 1397c478bd9Sstevel@tonic-gate * It also comes in single and quadruple versions. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate#define BAD NOT 1427c478bd9Sstevel@tonic-gate#define BAD4 NOT4 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate#define DONE \ 1457c478bd9Sstevel@tonic-gate done; \ 1467c478bd9Sstevel@tonic-gate .align 32 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate/* 1497c478bd9Sstevel@tonic-gate * TRAP vectors to the trap() function. 1507c478bd9Sstevel@tonic-gate * It's main use is for user errors. 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate#if !defined(lint) 1537c478bd9Sstevel@tonic-gate .global trap 1547c478bd9Sstevel@tonic-gate#endif /* !lint */ 1557c478bd9Sstevel@tonic-gate#define TRAP(arg) \ 1567c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1577c478bd9Sstevel@tonic-gate set trap, %g1 ;\ 1587c478bd9Sstevel@tonic-gate mov arg, %g3 ;\ 1597c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1607c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1617c478bd9Sstevel@tonic-gate .align 32 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate/* 16459f2ff5cSedp * SYSCALL is used for unsupported syscall interfaces (with 'which' 16559f2ff5cSedp * set to 'nosys') and legacy support of old SunOS 4.x syscalls (with 16659f2ff5cSedp * 'which' set to 'syscall_trap32'). 16759f2ff5cSedp * 16859f2ff5cSedp * The SYSCALL_TRAP* macros are used for syscall entry points. 16959f2ff5cSedp * SYSCALL_TRAP is used to support LP64 syscalls and SYSCALL_TRAP32 17059f2ff5cSedp * is used to support ILP32. Each macro can only be used once 17159f2ff5cSedp * since they each define a symbol. The symbols are used as hot patch 17259f2ff5cSedp * points by the brand infrastructure to dynamically enable and disable 17359f2ff5cSedp * brand syscall interposition. See the comments around BRAND_CALLBACK 17459f2ff5cSedp * and brand_plat_interposition_enable() for more information. 1757c478bd9Sstevel@tonic-gate */ 1764a75c0c1Sedp#define SYSCALL_NOTT(which) \ 1777c478bd9Sstevel@tonic-gate set (which), %g1 ;\ 1787c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1797c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1807c478bd9Sstevel@tonic-gate .align 32 1817c478bd9Sstevel@tonic-gate 18259f2ff5cSedp#define SYSCALL(which) \ 18359f2ff5cSedp TT_TRACE(trace_gen) ;\ 18459f2ff5cSedp SYSCALL_NOTT(which) 18559f2ff5cSedp 18659f2ff5cSedp#define SYSCALL_TRAP32 \ 18759f2ff5cSedp TT_TRACE(trace_gen) ;\ 18859f2ff5cSedp ALTENTRY(syscall_trap32_patch_point) \ 18959f2ff5cSedp SYSCALL_NOTT(syscall_trap32) 19059f2ff5cSedp 19159f2ff5cSedp#define SYSCALL_TRAP \ 19259f2ff5cSedp TT_TRACE(trace_gen) ;\ 19359f2ff5cSedp ALTENTRY(syscall_trap_patch_point) \ 19459f2ff5cSedp SYSCALL_NOTT(syscall_trap) 19559f2ff5cSedp 19650eff769Smb158278#define FLUSHW(h_name) \ 19750eff769Smb158278 .global h_name ;\ 19850eff769Smb158278h_name: ;\ 1997c478bd9Sstevel@tonic-gate set trap, %g1 ;\ 2007c478bd9Sstevel@tonic-gate mov T_FLUSHW, %g3 ;\ 2017c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2027c478bd9Sstevel@tonic-gate save ;\ 2037c478bd9Sstevel@tonic-gate flushw ;\ 2047c478bd9Sstevel@tonic-gate restore ;\ 2057c478bd9Sstevel@tonic-gate FAST_TRAP_DONE ;\ 2067c478bd9Sstevel@tonic-gate .align 32 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate/* 2097c478bd9Sstevel@tonic-gate * GOTO just jumps to a label. 2107c478bd9Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate#define GOTO(label) \ 2137c478bd9Sstevel@tonic-gate .global label ;\ 2147c478bd9Sstevel@tonic-gate ba,a label ;\ 2157c478bd9Sstevel@tonic-gate .empty ;\ 2167c478bd9Sstevel@tonic-gate .align 32 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate/* 2197c478bd9Sstevel@tonic-gate * GOTO_TT just jumps to a label. 2207c478bd9Sstevel@tonic-gate * correctable ECC error traps at level 0 and 1 will use this macro. 2217c478bd9Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate#define GOTO_TT(label, ttlabel) \ 2247c478bd9Sstevel@tonic-gate .global label ;\ 2257c478bd9Sstevel@tonic-gate TT_TRACE(ttlabel) ;\ 2267c478bd9Sstevel@tonic-gate ba,a label ;\ 2277c478bd9Sstevel@tonic-gate .empty ;\ 2287c478bd9Sstevel@tonic-gate .align 32 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate/* 2317c478bd9Sstevel@tonic-gate * Privileged traps 2327c478bd9Sstevel@tonic-gate * Takes breakpoint if privileged, calls trap() if not. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate#define PRIV(label) \ 2357c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 ;\ 2367c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g1 ;\ 2377c478bd9Sstevel@tonic-gate bnz label ;\ 2387c478bd9Sstevel@tonic-gate rdpr %tt, %g3 ;\ 2397c478bd9Sstevel@tonic-gate set trap, %g1 ;\ 2407c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 2417c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2427c478bd9Sstevel@tonic-gate .align 32 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate/* 2467c478bd9Sstevel@tonic-gate * DTrace traps. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate#define DTRACE_PID \ 2497c478bd9Sstevel@tonic-gate .global dtrace_pid_probe ;\ 2507c478bd9Sstevel@tonic-gate set dtrace_pid_probe, %g1 ;\ 2517c478bd9Sstevel@tonic-gate ba,pt %xcc, user_trap ;\ 2527c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2537c478bd9Sstevel@tonic-gate .align 32 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate#define DTRACE_RETURN \ 2567c478bd9Sstevel@tonic-gate .global dtrace_return_probe ;\ 2577c478bd9Sstevel@tonic-gate set dtrace_return_probe, %g1 ;\ 2587c478bd9Sstevel@tonic-gate ba,pt %xcc, user_trap ;\ 2597c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2607c478bd9Sstevel@tonic-gate .align 32 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate/* 2637c478bd9Sstevel@tonic-gate * REGISTER WINDOW MANAGEMENT MACROS 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate/* 2677c478bd9Sstevel@tonic-gate * various convenient units of padding 2687c478bd9Sstevel@tonic-gate */ 2697c478bd9Sstevel@tonic-gate#define SKIP(n) .skip 4*(n) 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate/* 2727c478bd9Sstevel@tonic-gate * CLEAN_WINDOW is the simple handler for cleaning a register window. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate#define CLEAN_WINDOW \ 2757c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 2767c478bd9Sstevel@tonic-gate rdpr %cleanwin, %l0; inc %l0; wrpr %l0, %cleanwin ;\ 2777c478bd9Sstevel@tonic-gate clr %l0; clr %l1; clr %l2; clr %l3 ;\ 2787c478bd9Sstevel@tonic-gate clr %l4; clr %l5; clr %l6; clr %l7 ;\ 2797c478bd9Sstevel@tonic-gate clr %o0; clr %o1; clr %o2; clr %o3 ;\ 2807c478bd9Sstevel@tonic-gate clr %o4; clr %o5; clr %o6; clr %o7 ;\ 2817c478bd9Sstevel@tonic-gate retry; .align 128 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate#if !defined(lint) 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate/* 2867c478bd9Sstevel@tonic-gate * If we get an unresolved tlb miss while in a window handler, the fault 2877c478bd9Sstevel@tonic-gate * handler will resume execution at the last instruction of the window 2887c478bd9Sstevel@tonic-gate * hander, instead of delivering the fault to the kernel. Spill handlers 2897c478bd9Sstevel@tonic-gate * use this to spill windows into the wbuf. 2907c478bd9Sstevel@tonic-gate * 2917c478bd9Sstevel@tonic-gate * The mixed handler works by checking %sp, and branching to the correct 2927c478bd9Sstevel@tonic-gate * handler. This is done by branching back to label 1: for 32b frames, 2937c478bd9Sstevel@tonic-gate * or label 2: for 64b frames; which implies the handler order is: 32b, 2947c478bd9Sstevel@tonic-gate * 64b, mixed. The 1: and 2: labels are offset into the routines to 2957c478bd9Sstevel@tonic-gate * allow the branchs' delay slots to contain useful instructions. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate/* 2997c478bd9Sstevel@tonic-gate * SPILL_32bit spills a 32-bit-wide kernel register window. It 3007c478bd9Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the 3017c478bd9Sstevel@tonic-gate * same. The stack pointer is required to be eight-byte aligned even 3027c478bd9Sstevel@tonic-gate * though this code only needs it to be four-byte aligned. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate#define SPILL_32bit(tail) \ 3057c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 3067c478bd9Sstevel@tonic-gate1: st %l0, [%sp + 0] ;\ 3077c478bd9Sstevel@tonic-gate st %l1, [%sp + 4] ;\ 3087c478bd9Sstevel@tonic-gate st %l2, [%sp + 8] ;\ 3097c478bd9Sstevel@tonic-gate st %l3, [%sp + 12] ;\ 3107c478bd9Sstevel@tonic-gate st %l4, [%sp + 16] ;\ 3117c478bd9Sstevel@tonic-gate st %l5, [%sp + 20] ;\ 3127c478bd9Sstevel@tonic-gate st %l6, [%sp + 24] ;\ 3137c478bd9Sstevel@tonic-gate st %l7, [%sp + 28] ;\ 3147c478bd9Sstevel@tonic-gate st %i0, [%sp + 32] ;\ 3157c478bd9Sstevel@tonic-gate st %i1, [%sp + 36] ;\ 3167c478bd9Sstevel@tonic-gate st %i2, [%sp + 40] ;\ 3177c478bd9Sstevel@tonic-gate st %i3, [%sp + 44] ;\ 3187c478bd9Sstevel@tonic-gate st %i4, [%sp + 48] ;\ 3197c478bd9Sstevel@tonic-gate st %i5, [%sp + 52] ;\ 3207c478bd9Sstevel@tonic-gate st %i6, [%sp + 56] ;\ 3217c478bd9Sstevel@tonic-gate st %i7, [%sp + 60] ;\ 3227c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3237c478bd9Sstevel@tonic-gate saved ;\ 3247c478bd9Sstevel@tonic-gate retry ;\ 3257c478bd9Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 3267c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3277c478bd9Sstevel@tonic-gate .empty 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate/* 3307c478bd9Sstevel@tonic-gate * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit 3317c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 3327c478bd9Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 3337c478bd9Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte 3347c478bd9Sstevel@tonic-gate * aligned. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate#define SPILL_32bit_asi(asi_num, tail) \ 3377c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 3387c478bd9Sstevel@tonic-gate1: sta %l0, [%sp + %g0]asi_num ;\ 3397c478bd9Sstevel@tonic-gate mov 4, %g1 ;\ 3407c478bd9Sstevel@tonic-gate sta %l1, [%sp + %g1]asi_num ;\ 3417c478bd9Sstevel@tonic-gate mov 8, %g2 ;\ 3427c478bd9Sstevel@tonic-gate sta %l2, [%sp + %g2]asi_num ;\ 3437c478bd9Sstevel@tonic-gate mov 12, %g3 ;\ 3447c478bd9Sstevel@tonic-gate sta %l3, [%sp + %g3]asi_num ;\ 3457c478bd9Sstevel@tonic-gate add %sp, 16, %g4 ;\ 3467c478bd9Sstevel@tonic-gate sta %l4, [%g4 + %g0]asi_num ;\ 3477c478bd9Sstevel@tonic-gate sta %l5, [%g4 + %g1]asi_num ;\ 3487c478bd9Sstevel@tonic-gate sta %l6, [%g4 + %g2]asi_num ;\ 3497c478bd9Sstevel@tonic-gate sta %l7, [%g4 + %g3]asi_num ;\ 3507c478bd9Sstevel@tonic-gate add %g4, 16, %g4 ;\ 3517c478bd9Sstevel@tonic-gate sta %i0, [%g4 + %g0]asi_num ;\ 3527c478bd9Sstevel@tonic-gate sta %i1, [%g4 + %g1]asi_num ;\ 3537c478bd9Sstevel@tonic-gate sta %i2, [%g4 + %g2]asi_num ;\ 3547c478bd9Sstevel@tonic-gate sta %i3, [%g4 + %g3]asi_num ;\ 3557c478bd9Sstevel@tonic-gate add %g4, 16, %g4 ;\ 3567c478bd9Sstevel@tonic-gate sta %i4, [%g4 + %g0]asi_num ;\ 3577c478bd9Sstevel@tonic-gate sta %i5, [%g4 + %g1]asi_num ;\ 3587c478bd9Sstevel@tonic-gate sta %i6, [%g4 + %g2]asi_num ;\ 3597c478bd9Sstevel@tonic-gate sta %i7, [%g4 + %g3]asi_num ;\ 3607c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3617c478bd9Sstevel@tonic-gate saved ;\ 3627c478bd9Sstevel@tonic-gate retry ;\ 3637c478bd9Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 3647c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3657c478bd9Sstevel@tonic-gate .empty 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate/* 3687c478bd9Sstevel@tonic-gate * SPILL_32bit_tt1 spills a 32-bit-wide register window into a 32-bit 3697c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 3707c478bd9Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 3717c478bd9Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 3727c478bd9Sstevel@tonic-gate * pointer is required to be eight-byte aligned even though this code 3737c478bd9Sstevel@tonic-gate * only needs it to be four-byte aligned. 3747c478bd9Sstevel@tonic-gate */ 3757c478bd9Sstevel@tonic-gate#define SPILL_32bit_tt1(asi_num, tail) \ 3767c478bd9Sstevel@tonic-gate mov asi_num, %asi ;\ 3777c478bd9Sstevel@tonic-gate1: srl %sp, 0, %sp ;\ 3787c478bd9Sstevel@tonic-gate sta %l0, [%sp + 0]%asi ;\ 3797c478bd9Sstevel@tonic-gate sta %l1, [%sp + 4]%asi ;\ 3807c478bd9Sstevel@tonic-gate sta %l2, [%sp + 8]%asi ;\ 3817c478bd9Sstevel@tonic-gate sta %l3, [%sp + 12]%asi ;\ 3827c478bd9Sstevel@tonic-gate sta %l4, [%sp + 16]%asi ;\ 3837c478bd9Sstevel@tonic-gate sta %l5, [%sp + 20]%asi ;\ 3847c478bd9Sstevel@tonic-gate sta %l6, [%sp + 24]%asi ;\ 3857c478bd9Sstevel@tonic-gate sta %l7, [%sp + 28]%asi ;\ 3867c478bd9Sstevel@tonic-gate sta %i0, [%sp + 32]%asi ;\ 3877c478bd9Sstevel@tonic-gate sta %i1, [%sp + 36]%asi ;\ 3887c478bd9Sstevel@tonic-gate sta %i2, [%sp + 40]%asi ;\ 3897c478bd9Sstevel@tonic-gate sta %i3, [%sp + 44]%asi ;\ 3907c478bd9Sstevel@tonic-gate sta %i4, [%sp + 48]%asi ;\ 3917c478bd9Sstevel@tonic-gate sta %i5, [%sp + 52]%asi ;\ 3927c478bd9Sstevel@tonic-gate sta %i6, [%sp + 56]%asi ;\ 3937c478bd9Sstevel@tonic-gate sta %i7, [%sp + 60]%asi ;\ 3947c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3957c478bd9Sstevel@tonic-gate saved ;\ 3967c478bd9Sstevel@tonic-gate retry ;\ 3977c478bd9Sstevel@tonic-gate SKIP(31-20-TT_TRACE_L_INS) ;\ 3987c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3997c478bd9Sstevel@tonic-gate .empty 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate/* 4037c478bd9Sstevel@tonic-gate * FILL_32bit fills a 32-bit-wide kernel register window. It assumes 4047c478bd9Sstevel@tonic-gate * that the kernel context and the nucleus context are the same. The 4057c478bd9Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned even though this 4067c478bd9Sstevel@tonic-gate * code only needs it to be four-byte aligned. 4077c478bd9Sstevel@tonic-gate */ 4087c478bd9Sstevel@tonic-gate#define FILL_32bit(tail) \ 4097c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 4107c478bd9Sstevel@tonic-gate1: TT_TRACE_L(trace_win) ;\ 4117c478bd9Sstevel@tonic-gate ld [%sp + 0], %l0 ;\ 4127c478bd9Sstevel@tonic-gate ld [%sp + 4], %l1 ;\ 4137c478bd9Sstevel@tonic-gate ld [%sp + 8], %l2 ;\ 4147c478bd9Sstevel@tonic-gate ld [%sp + 12], %l3 ;\ 4157c478bd9Sstevel@tonic-gate ld [%sp + 16], %l4 ;\ 4167c478bd9Sstevel@tonic-gate ld [%sp + 20], %l5 ;\ 4177c478bd9Sstevel@tonic-gate ld [%sp + 24], %l6 ;\ 4187c478bd9Sstevel@tonic-gate ld [%sp + 28], %l7 ;\ 4197c478bd9Sstevel@tonic-gate ld [%sp + 32], %i0 ;\ 4207c478bd9Sstevel@tonic-gate ld [%sp + 36], %i1 ;\ 4217c478bd9Sstevel@tonic-gate ld [%sp + 40], %i2 ;\ 4227c478bd9Sstevel@tonic-gate ld [%sp + 44], %i3 ;\ 4237c478bd9Sstevel@tonic-gate ld [%sp + 48], %i4 ;\ 4247c478bd9Sstevel@tonic-gate ld [%sp + 52], %i5 ;\ 4257c478bd9Sstevel@tonic-gate ld [%sp + 56], %i6 ;\ 4267c478bd9Sstevel@tonic-gate ld [%sp + 60], %i7 ;\ 4277c478bd9Sstevel@tonic-gate restored ;\ 4287c478bd9Sstevel@tonic-gate retry ;\ 4297c478bd9Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 4307c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 4317c478bd9Sstevel@tonic-gate .empty 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate/* 4347c478bd9Sstevel@tonic-gate * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit 4357c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 4367c478bd9Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 4377c478bd9Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte 4387c478bd9Sstevel@tonic-gate * aligned. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate#define FILL_32bit_asi(asi_num, tail) \ 4417c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 4427c478bd9Sstevel@tonic-gate1: TT_TRACE_L(trace_win) ;\ 4437c478bd9Sstevel@tonic-gate mov 4, %g1 ;\ 4447c478bd9Sstevel@tonic-gate lda [%sp + %g0]asi_num, %l0 ;\ 4457c478bd9Sstevel@tonic-gate mov 8, %g2 ;\ 4467c478bd9Sstevel@tonic-gate lda [%sp + %g1]asi_num, %l1 ;\ 4477c478bd9Sstevel@tonic-gate mov 12, %g3 ;\ 4487c478bd9Sstevel@tonic-gate lda [%sp + %g2]asi_num, %l2 ;\ 4497c478bd9Sstevel@tonic-gate lda [%sp + %g3]asi_num, %l3 ;\ 4507c478bd9Sstevel@tonic-gate add %sp, 16, %g4 ;\ 4517c478bd9Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %l4 ;\ 4527c478bd9Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %l5 ;\ 4537c478bd9Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %l6 ;\ 4547c478bd9Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %l7 ;\ 4557c478bd9Sstevel@tonic-gate add %g4, 16, %g4 ;\ 4567c478bd9Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %i0 ;\ 4577c478bd9Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %i1 ;\ 4587c478bd9Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %i2 ;\ 4597c478bd9Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %i3 ;\ 4607c478bd9Sstevel@tonic-gate add %g4, 16, %g4 ;\ 4617c478bd9Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %i4 ;\ 4627c478bd9Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %i5 ;\ 4637c478bd9Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %i6 ;\ 4647c478bd9Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %i7 ;\ 4657c478bd9Sstevel@tonic-gate restored ;\ 4667c478bd9Sstevel@tonic-gate retry ;\ 4677c478bd9Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 4687c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 4697c478bd9Sstevel@tonic-gate .empty 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate/* 4727c478bd9Sstevel@tonic-gate * FILL_32bit_tt1 fills a 32-bit-wide register window from a 32-bit 4737c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 4747c478bd9Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 4757c478bd9Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 4767c478bd9Sstevel@tonic-gate * pointer is required to be eight-byte aligned even though this code 4777c478bd9Sstevel@tonic-gate * only needs it to be four-byte aligned. 4787c478bd9Sstevel@tonic-gate */ 4797c478bd9Sstevel@tonic-gate#define FILL_32bit_tt1(asi_num, tail) \ 4807c478bd9Sstevel@tonic-gate mov asi_num, %asi ;\ 4817c478bd9Sstevel@tonic-gate1: srl %sp, 0, %sp ;\ 4827c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 4837c478bd9Sstevel@tonic-gate lda [%sp + 0]%asi, %l0 ;\ 4847c478bd9Sstevel@tonic-gate lda [%sp + 4]%asi, %l1 ;\ 4857c478bd9Sstevel@tonic-gate lda [%sp + 8]%asi, %l2 ;\ 4867c478bd9Sstevel@tonic-gate lda [%sp + 12]%asi, %l3 ;\ 4877c478bd9Sstevel@tonic-gate lda [%sp + 16]%asi, %l4 ;\ 4887c478bd9Sstevel@tonic-gate lda [%sp + 20]%asi, %l5 ;\ 4897c478bd9Sstevel@tonic-gate lda [%sp + 24]%asi, %l6 ;\ 4907c478bd9Sstevel@tonic-gate lda [%sp + 28]%asi, %l7 ;\ 4917c478bd9Sstevel@tonic-gate lda [%sp + 32]%asi, %i0 ;\ 4927c478bd9Sstevel@tonic-gate lda [%sp + 36]%asi, %i1 ;\ 4937c478bd9Sstevel@tonic-gate lda [%sp + 40]%asi, %i2 ;\ 4947c478bd9Sstevel@tonic-gate lda [%sp + 44]%asi, %i3 ;\ 4957c478bd9Sstevel@tonic-gate lda [%sp + 48]%asi, %i4 ;\ 4967c478bd9Sstevel@tonic-gate lda [%sp + 52]%asi, %i5 ;\ 4977c478bd9Sstevel@tonic-gate lda [%sp + 56]%asi, %i6 ;\ 4987c478bd9Sstevel@tonic-gate lda [%sp + 60]%asi, %i7 ;\ 4997c478bd9Sstevel@tonic-gate restored ;\ 5007c478bd9Sstevel@tonic-gate retry ;\ 5017c478bd9Sstevel@tonic-gate SKIP(31-20-TT_TRACE_L_INS) ;\ 5027c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 5037c478bd9Sstevel@tonic-gate .empty 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate/* 5077c478bd9Sstevel@tonic-gate * SPILL_64bit spills a 64-bit-wide kernel register window. It 5087c478bd9Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the 5097c478bd9Sstevel@tonic-gate * same. The stack pointer is required to be eight-byte aligned. 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate#define SPILL_64bit(tail) \ 5127c478bd9Sstevel@tonic-gate2: stx %l0, [%sp + V9BIAS64 + 0] ;\ 5137c478bd9Sstevel@tonic-gate stx %l1, [%sp + V9BIAS64 + 8] ;\ 5147c478bd9Sstevel@tonic-gate stx %l2, [%sp + V9BIAS64 + 16] ;\ 5157c478bd9Sstevel@tonic-gate stx %l3, [%sp + V9BIAS64 + 24] ;\ 5167c478bd9Sstevel@tonic-gate stx %l4, [%sp + V9BIAS64 + 32] ;\ 5177c478bd9Sstevel@tonic-gate stx %l5, [%sp + V9BIAS64 + 40] ;\ 5187c478bd9Sstevel@tonic-gate stx %l6, [%sp + V9BIAS64 + 48] ;\ 5197c478bd9Sstevel@tonic-gate stx %l7, [%sp + V9BIAS64 + 56] ;\ 5207c478bd9Sstevel@tonic-gate stx %i0, [%sp + V9BIAS64 + 64] ;\ 5217c478bd9Sstevel@tonic-gate stx %i1, [%sp + V9BIAS64 + 72] ;\ 5227c478bd9Sstevel@tonic-gate stx %i2, [%sp + V9BIAS64 + 80] ;\ 5237c478bd9Sstevel@tonic-gate stx %i3, [%sp + V9BIAS64 + 88] ;\ 5247c478bd9Sstevel@tonic-gate stx %i4, [%sp + V9BIAS64 + 96] ;\ 5257c478bd9Sstevel@tonic-gate stx %i5, [%sp + V9BIAS64 + 104] ;\ 5267c478bd9Sstevel@tonic-gate stx %i6, [%sp + V9BIAS64 + 112] ;\ 5277c478bd9Sstevel@tonic-gate stx %i7, [%sp + V9BIAS64 + 120] ;\ 5287c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5297c478bd9Sstevel@tonic-gate saved ;\ 5307c478bd9Sstevel@tonic-gate retry ;\ 5317c478bd9Sstevel@tonic-gate SKIP(31-18-TT_TRACE_L_INS) ;\ 5327c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5337c478bd9Sstevel@tonic-gate .empty 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate/* 5367c478bd9Sstevel@tonic-gate * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit 5377c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 5387c478bd9Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 5397c478bd9Sstevel@tonic-gate * aligned. 5407c478bd9Sstevel@tonic-gate */ 5417c478bd9Sstevel@tonic-gate#define SPILL_64bit_asi(asi_num, tail) \ 5427c478bd9Sstevel@tonic-gate mov 0 + V9BIAS64, %g1 ;\ 5437c478bd9Sstevel@tonic-gate2: stxa %l0, [%sp + %g1]asi_num ;\ 5447c478bd9Sstevel@tonic-gate mov 8 + V9BIAS64, %g2 ;\ 5457c478bd9Sstevel@tonic-gate stxa %l1, [%sp + %g2]asi_num ;\ 5467c478bd9Sstevel@tonic-gate mov 16 + V9BIAS64, %g3 ;\ 5477c478bd9Sstevel@tonic-gate stxa %l2, [%sp + %g3]asi_num ;\ 5487c478bd9Sstevel@tonic-gate mov 24 + V9BIAS64, %g4 ;\ 5497c478bd9Sstevel@tonic-gate stxa %l3, [%sp + %g4]asi_num ;\ 5507c478bd9Sstevel@tonic-gate add %sp, 32, %g5 ;\ 5517c478bd9Sstevel@tonic-gate stxa %l4, [%g5 + %g1]asi_num ;\ 5527c478bd9Sstevel@tonic-gate stxa %l5, [%g5 + %g2]asi_num ;\ 5537c478bd9Sstevel@tonic-gate stxa %l6, [%g5 + %g3]asi_num ;\ 5547c478bd9Sstevel@tonic-gate stxa %l7, [%g5 + %g4]asi_num ;\ 5557c478bd9Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5567c478bd9Sstevel@tonic-gate stxa %i0, [%g5 + %g1]asi_num ;\ 5577c478bd9Sstevel@tonic-gate stxa %i1, [%g5 + %g2]asi_num ;\ 5587c478bd9Sstevel@tonic-gate stxa %i2, [%g5 + %g3]asi_num ;\ 5597c478bd9Sstevel@tonic-gate stxa %i3, [%g5 + %g4]asi_num ;\ 5607c478bd9Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5617c478bd9Sstevel@tonic-gate stxa %i4, [%g5 + %g1]asi_num ;\ 5627c478bd9Sstevel@tonic-gate stxa %i5, [%g5 + %g2]asi_num ;\ 5637c478bd9Sstevel@tonic-gate stxa %i6, [%g5 + %g3]asi_num ;\ 5647c478bd9Sstevel@tonic-gate stxa %i7, [%g5 + %g4]asi_num ;\ 5657c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5667c478bd9Sstevel@tonic-gate saved ;\ 5677c478bd9Sstevel@tonic-gate retry ;\ 5687c478bd9Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 5697c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5707c478bd9Sstevel@tonic-gate .empty 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate/* 5737c478bd9Sstevel@tonic-gate * SPILL_64bit_tt1 spills a 64-bit-wide register window into a 64-bit 5747c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 5757c478bd9Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 5767c478bd9Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 5777c478bd9Sstevel@tonic-gate * pointer is required to be eight-byte aligned. 5787c478bd9Sstevel@tonic-gate */ 5797c478bd9Sstevel@tonic-gate#define SPILL_64bit_tt1(asi_num, tail) \ 5807c478bd9Sstevel@tonic-gate mov asi_num, %asi ;\ 5817c478bd9Sstevel@tonic-gate2: stxa %l0, [%sp + V9BIAS64 + 0]%asi ;\ 5827c478bd9Sstevel@tonic-gate stxa %l1, [%sp + V9BIAS64 + 8]%asi ;\ 5837c478bd9Sstevel@tonic-gate stxa %l2, [%sp + V9BIAS64 + 16]%asi ;\ 5847c478bd9Sstevel@tonic-gate stxa %l3, [%sp + V9BIAS64 + 24]%asi ;\ 5857c478bd9Sstevel@tonic-gate stxa %l4, [%sp + V9BIAS64 + 32]%asi ;\ 5867c478bd9Sstevel@tonic-gate stxa %l5, [%sp + V9BIAS64 + 40]%asi ;\ 5877c478bd9Sstevel@tonic-gate stxa %l6, [%sp + V9BIAS64 + 48]%asi ;\ 5887c478bd9Sstevel@tonic-gate stxa %l7, [%sp + V9BIAS64 + 56]%asi ;\ 5897c478bd9Sstevel@tonic-gate stxa %i0, [%sp + V9BIAS64 + 64]%asi ;\ 5907c478bd9Sstevel@tonic-gate stxa %i1, [%sp + V9BIAS64 + 72]%asi ;\ 5917c478bd9Sstevel@tonic-gate stxa %i2, [%sp + V9BIAS64 + 80]%asi ;\ 5927c478bd9Sstevel@tonic-gate stxa %i3, [%sp + V9BIAS64 + 88]%asi ;\ 5937c478bd9Sstevel@tonic-gate stxa %i4, [%sp + V9BIAS64 + 96]%asi ;\ 5947c478bd9Sstevel@tonic-gate stxa %i5, [%sp + V9BIAS64 + 104]%asi ;\ 5957c478bd9Sstevel@tonic-gate stxa %i6, [%sp + V9BIAS64 + 112]%asi ;\ 5967c478bd9Sstevel@tonic-gate stxa %i7, [%sp + V9BIAS64 + 120]%asi ;\ 5977c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5987c478bd9Sstevel@tonic-gate saved ;\ 5997c478bd9Sstevel@tonic-gate retry ;\ 6007c478bd9Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 6017c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 6027c478bd9Sstevel@tonic-gate .empty 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate/* 6067c478bd9Sstevel@tonic-gate * FILL_64bit fills a 64-bit-wide kernel register window. It assumes 6077c478bd9Sstevel@tonic-gate * that the kernel context and the nucleus context are the same. The 6087c478bd9Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned. 6097c478bd9Sstevel@tonic-gate */ 6107c478bd9Sstevel@tonic-gate#define FILL_64bit(tail) \ 6117c478bd9Sstevel@tonic-gate2: TT_TRACE_L(trace_win) ;\ 6127c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 0], %l0 ;\ 6137c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 8], %l1 ;\ 6147c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 16], %l2 ;\ 6157c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 24], %l3 ;\ 6167c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 32], %l4 ;\ 6177c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 40], %l5 ;\ 6187c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 48], %l6 ;\ 6197c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 56], %l7 ;\ 6207c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 64], %i0 ;\ 6217c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 72], %i1 ;\ 6227c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 80], %i2 ;\ 6237c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 88], %i3 ;\ 6247c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 96], %i4 ;\ 6257c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 104], %i5 ;\ 6267c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 112], %i6 ;\ 6277c478bd9Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 120], %i7 ;\ 6287c478bd9Sstevel@tonic-gate restored ;\ 6297c478bd9Sstevel@tonic-gate retry ;\ 6307c478bd9Sstevel@tonic-gate SKIP(31-18-TT_TRACE_L_INS) ;\ 6317c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 6327c478bd9Sstevel@tonic-gate .empty 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate/* 6357c478bd9Sstevel@tonic-gate * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit 6367c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 6377c478bd9Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 6387c478bd9Sstevel@tonic-gate * aligned. 6397c478bd9Sstevel@tonic-gate */ 6407c478bd9Sstevel@tonic-gate#define FILL_64bit_asi(asi_num, tail) \ 6417c478bd9Sstevel@tonic-gate mov V9BIAS64 + 0, %g1 ;\ 6427c478bd9Sstevel@tonic-gate2: TT_TRACE_L(trace_win) ;\ 6437c478bd9Sstevel@tonic-gate ldxa [%sp + %g1]asi_num, %l0 ;\ 6447c478bd9Sstevel@tonic-gate mov V9BIAS64 + 8, %g2 ;\ 6457c478bd9Sstevel@tonic-gate ldxa [%sp + %g2]asi_num, %l1 ;\ 6467c478bd9Sstevel@tonic-gate mov V9BIAS64 + 16, %g3 ;\ 6477c478bd9Sstevel@tonic-gate ldxa [%sp + %g3]asi_num, %l2 ;\ 6487c478bd9Sstevel@tonic-gate mov V9BIAS64 + 24, %g4 ;\ 6497c478bd9Sstevel@tonic-gate ldxa [%sp + %g4]asi_num, %l3 ;\ 6507c478bd9Sstevel@tonic-gate add %sp, 32, %g5 ;\ 6517c478bd9Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %l4 ;\ 6527c478bd9Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %l5 ;\ 6537c478bd9Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %l6 ;\ 6547c478bd9Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %l7 ;\ 6557c478bd9Sstevel@tonic-gate add %g5, 32, %g5 ;\ 6567c478bd9Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %i0 ;\ 6577c478bd9Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %i1 ;\ 6587c478bd9Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %i2 ;\ 6597c478bd9Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %i3 ;\ 6607c478bd9Sstevel@tonic-gate add %g5, 32, %g5 ;\ 6617c478bd9Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %i4 ;\ 6627c478bd9Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %i5 ;\ 6637c478bd9Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %i6 ;\ 6647c478bd9Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %i7 ;\ 6657c478bd9Sstevel@tonic-gate restored ;\ 6667c478bd9Sstevel@tonic-gate retry ;\ 6677c478bd9Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 6687c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 6697c478bd9Sstevel@tonic-gate .empty 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate/* 6727c478bd9Sstevel@tonic-gate * FILL_64bit_tt1 fills a 64-bit-wide register window from a 64-bit 6737c478bd9Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 6747c478bd9Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 6757c478bd9Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 6767c478bd9Sstevel@tonic-gate * pointer is required to be eight-byte aligned. 6777c478bd9Sstevel@tonic-gate */ 6787c478bd9Sstevel@tonic-gate#define FILL_64bit_tt1(asi_num, tail) \ 6797c478bd9Sstevel@tonic-gate mov asi_num, %asi ;\ 6807c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 6817c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 0]%asi, %l0 ;\ 6827c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 8]%asi, %l1 ;\ 6837c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 16]%asi, %l2 ;\ 6847c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 24]%asi, %l3 ;\ 6857c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 32]%asi, %l4 ;\ 6867c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 40]%asi, %l5 ;\ 6877c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 48]%asi, %l6 ;\ 6887c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 56]%asi, %l7 ;\ 6897c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 64]%asi, %i0 ;\ 6907c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 72]%asi, %i1 ;\ 6917c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 80]%asi, %i2 ;\ 6927c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 88]%asi, %i3 ;\ 6937c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 96]%asi, %i4 ;\ 6947c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 104]%asi, %i5 ;\ 6957c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 112]%asi, %i6 ;\ 6967c478bd9Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 120]%asi, %i7 ;\ 6977c478bd9Sstevel@tonic-gate restored ;\ 6987c478bd9Sstevel@tonic-gate retry ;\ 6997c478bd9Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 7007c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 7017c478bd9Sstevel@tonic-gate .empty 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate#endif /* !lint */ 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate/* 7067c478bd9Sstevel@tonic-gate * SPILL_mixed spills either size window, depending on 7077c478bd9Sstevel@tonic-gate * whether %sp is even or odd, to a 32-bit address space. 7087c478bd9Sstevel@tonic-gate * This may only be used in conjunction with SPILL_32bit/ 7097c478bd9Sstevel@tonic-gate * SPILL_64bit. New versions of SPILL_mixed_{tt1,asi} would be 7107c478bd9Sstevel@tonic-gate * needed for use with SPILL_{32,64}bit_{tt1,asi}. Particular 7117c478bd9Sstevel@tonic-gate * attention should be paid to the instructions that belong 7127c478bd9Sstevel@tonic-gate * in the delay slots of the branches depending on the type 7137c478bd9Sstevel@tonic-gate * of spill handler being branched to. 7147c478bd9Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd. 7157c478bd9Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel. 7167c478bd9Sstevel@tonic-gate */ 7177c478bd9Sstevel@tonic-gate#define SPILL_mixed \ 7187c478bd9Sstevel@tonic-gate btst 1, %sp ;\ 7197c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1b ;\ 7207c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 7217c478bd9Sstevel@tonic-gate ba,pt %xcc, 2b ;\ 7227c478bd9Sstevel@tonic-gate nop ;\ 7237c478bd9Sstevel@tonic-gate .align 128 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate/* 7267c478bd9Sstevel@tonic-gate * FILL_mixed(ASI) fills either size window, depending on 7277c478bd9Sstevel@tonic-gate * whether %sp is even or odd, from a 32-bit address space. 7287c478bd9Sstevel@tonic-gate * This may only be used in conjunction with FILL_32bit/ 7297c478bd9Sstevel@tonic-gate * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be 7307c478bd9Sstevel@tonic-gate * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular 7317c478bd9Sstevel@tonic-gate * attention should be paid to the instructions that belong 7327c478bd9Sstevel@tonic-gate * in the delay slots of the branches depending on the type 7337c478bd9Sstevel@tonic-gate * of fill handler being branched to. 7347c478bd9Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd. 7357c478bd9Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel. 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate#define FILL_mixed \ 7387c478bd9Sstevel@tonic-gate btst 1, %sp ;\ 7397c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1b ;\ 7407c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 7417c478bd9Sstevel@tonic-gate ba,pt %xcc, 2b ;\ 7427c478bd9Sstevel@tonic-gate nop ;\ 7437c478bd9Sstevel@tonic-gate .align 128 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate/* 7477c478bd9Sstevel@tonic-gate * SPILL_32clean/SPILL_64clean spill 32-bit and 64-bit register windows, 7487c478bd9Sstevel@tonic-gate * respectively, into the address space via the designated asi. The 7497c478bd9Sstevel@tonic-gate * unbiased stack pointer is required to be eight-byte aligned (even for 7507c478bd9Sstevel@tonic-gate * the 32-bit case even though this code does not require such strict 7517c478bd9Sstevel@tonic-gate * alignment). 7527c478bd9Sstevel@tonic-gate * 7537c478bd9Sstevel@tonic-gate * With SPARC v9 the spill trap takes precedence over the cleanwin trap 7547c478bd9Sstevel@tonic-gate * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save 7557c478bd9Sstevel@tonic-gate * will cause cwp + 2 to be spilled but will not clean cwp + 1. That 7567c478bd9Sstevel@tonic-gate * window may contain kernel data so in user_rtt we set wstate to call 7577c478bd9Sstevel@tonic-gate * these spill handlers on the first user spill trap. These handler then 7587c478bd9Sstevel@tonic-gate * spill the appropriate window but also back up a window and clean the 7597c478bd9Sstevel@tonic-gate * window that didn't get a cleanwin trap. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate#define SPILL_32clean(asi_num, tail) \ 7627c478bd9Sstevel@tonic-gate srl %sp, 0, %sp ;\ 7637c478bd9Sstevel@tonic-gate sta %l0, [%sp + %g0]asi_num ;\ 7647c478bd9Sstevel@tonic-gate mov 4, %g1 ;\ 7657c478bd9Sstevel@tonic-gate sta %l1, [%sp + %g1]asi_num ;\ 7667c478bd9Sstevel@tonic-gate mov 8, %g2 ;\ 7677c478bd9Sstevel@tonic-gate sta %l2, [%sp + %g2]asi_num ;\ 7687c478bd9Sstevel@tonic-gate mov 12, %g3 ;\ 7697c478bd9Sstevel@tonic-gate sta %l3, [%sp + %g3]asi_num ;\ 7707c478bd9Sstevel@tonic-gate add %sp, 16, %g4 ;\ 7717c478bd9Sstevel@tonic-gate sta %l4, [%g4 + %g0]asi_num ;\ 7727c478bd9Sstevel@tonic-gate sta %l5, [%g4 + %g1]asi_num ;\ 7737c478bd9Sstevel@tonic-gate sta %l6, [%g4 + %g2]asi_num ;\ 7747c478bd9Sstevel@tonic-gate sta %l7, [%g4 + %g3]asi_num ;\ 7757c478bd9Sstevel@tonic-gate add %g4, 16, %g4 ;\ 7767c478bd9Sstevel@tonic-gate sta %i0, [%g4 + %g0]asi_num ;\ 7777c478bd9Sstevel@tonic-gate sta %i1, [%g4 + %g1]asi_num ;\ 7787c478bd9Sstevel@tonic-gate sta %i2, [%g4 + %g2]asi_num ;\ 7797c478bd9Sstevel@tonic-gate sta %i3, [%g4 + %g3]asi_num ;\ 7807c478bd9Sstevel@tonic-gate add %g4, 16, %g4 ;\ 7817c478bd9Sstevel@tonic-gate sta %i4, [%g4 + %g0]asi_num ;\ 7827c478bd9Sstevel@tonic-gate sta %i5, [%g4 + %g1]asi_num ;\ 7837c478bd9Sstevel@tonic-gate sta %i6, [%g4 + %g2]asi_num ;\ 7847c478bd9Sstevel@tonic-gate sta %i7, [%g4 + %g3]asi_num ;\ 7857c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 7867c478bd9Sstevel@tonic-gate b .spill_clean ;\ 7877c478bd9Sstevel@tonic-gate mov WSTATE_USER32, %g7 ;\ 7887c478bd9Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 7897c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 7907c478bd9Sstevel@tonic-gate .empty 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate#define SPILL_64clean(asi_num, tail) \ 7937c478bd9Sstevel@tonic-gate mov 0 + V9BIAS64, %g1 ;\ 7947c478bd9Sstevel@tonic-gate stxa %l0, [%sp + %g1]asi_num ;\ 7957c478bd9Sstevel@tonic-gate mov 8 + V9BIAS64, %g2 ;\ 7967c478bd9Sstevel@tonic-gate stxa %l1, [%sp + %g2]asi_num ;\ 7977c478bd9Sstevel@tonic-gate mov 16 + V9BIAS64, %g3 ;\ 7987c478bd9Sstevel@tonic-gate stxa %l2, [%sp + %g3]asi_num ;\ 7997c478bd9Sstevel@tonic-gate mov 24 + V9BIAS64, %g4 ;\ 8007c478bd9Sstevel@tonic-gate stxa %l3, [%sp + %g4]asi_num ;\ 8017c478bd9Sstevel@tonic-gate add %sp, 32, %g5 ;\ 8027c478bd9Sstevel@tonic-gate stxa %l4, [%g5 + %g1]asi_num ;\ 8037c478bd9Sstevel@tonic-gate stxa %l5, [%g5 + %g2]asi_num ;\ 8047c478bd9Sstevel@tonic-gate stxa %l6, [%g5 + %g3]asi_num ;\ 8057c478bd9Sstevel@tonic-gate stxa %l7, [%g5 + %g4]asi_num ;\ 8067c478bd9Sstevel@tonic-gate add %g5, 32, %g5 ;\ 8077c478bd9Sstevel@tonic-gate stxa %i0, [%g5 + %g1]asi_num ;\ 8087c478bd9Sstevel@tonic-gate stxa %i1, [%g5 + %g2]asi_num ;\ 8097c478bd9Sstevel@tonic-gate stxa %i2, [%g5 + %g3]asi_num ;\ 8107c478bd9Sstevel@tonic-gate stxa %i3, [%g5 + %g4]asi_num ;\ 8117c478bd9Sstevel@tonic-gate add %g5, 32, %g5 ;\ 8127c478bd9Sstevel@tonic-gate stxa %i4, [%g5 + %g1]asi_num ;\ 8137c478bd9Sstevel@tonic-gate stxa %i5, [%g5 + %g2]asi_num ;\ 8147c478bd9Sstevel@tonic-gate stxa %i6, [%g5 + %g3]asi_num ;\ 8157c478bd9Sstevel@tonic-gate stxa %i7, [%g5 + %g4]asi_num ;\ 8167c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 8177c478bd9Sstevel@tonic-gate b .spill_clean ;\ 8187c478bd9Sstevel@tonic-gate mov WSTATE_USER64, %g7 ;\ 8197c478bd9Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 8207c478bd9Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 8217c478bd9Sstevel@tonic-gate .empty 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate/* 8257c478bd9Sstevel@tonic-gate * Floating point disabled. 8267c478bd9Sstevel@tonic-gate */ 8277c478bd9Sstevel@tonic-gate#define FP_DISABLED_TRAP \ 8287c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8297c478bd9Sstevel@tonic-gate ba,pt %xcc,.fp_disabled ;\ 8307c478bd9Sstevel@tonic-gate nop ;\ 8317c478bd9Sstevel@tonic-gate .align 32 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate/* 8347c478bd9Sstevel@tonic-gate * Floating point exceptions. 8357c478bd9Sstevel@tonic-gate */ 8367c478bd9Sstevel@tonic-gate#define FP_IEEE_TRAP \ 8377c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8387c478bd9Sstevel@tonic-gate ba,pt %xcc,.fp_ieee_exception ;\ 8397c478bd9Sstevel@tonic-gate nop ;\ 8407c478bd9Sstevel@tonic-gate .align 32 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate#define FP_TRAP \ 8437c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8447c478bd9Sstevel@tonic-gate ba,pt %xcc,.fp_exception ;\ 8457c478bd9Sstevel@tonic-gate nop ;\ 8467c478bd9Sstevel@tonic-gate .align 32 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate#if !defined(lint) 8497c478bd9Sstevel@tonic-gate/* 8507c478bd9Sstevel@tonic-gate * asynchronous traps at level 0 and level 1 8517c478bd9Sstevel@tonic-gate * 8527c478bd9Sstevel@tonic-gate * The first instruction must be a membar for UltraSPARC-III 8537c478bd9Sstevel@tonic-gate * to stop RED state entry if the store queue has many 8547c478bd9Sstevel@tonic-gate * pending bad stores (PRM, Chapter 11). 8557c478bd9Sstevel@tonic-gate */ 85625cf1a30Sjl139090#define ASYNC_TRAP(ttype, ttlabel, table_name)\ 85725cf1a30Sjl139090 .global table_name ;\ 85825cf1a30Sjl139090table_name: ;\ 8597c478bd9Sstevel@tonic-gate membar #Sync ;\ 8607c478bd9Sstevel@tonic-gate TT_TRACE(ttlabel) ;\ 8617c478bd9Sstevel@tonic-gate ba async_err ;\ 8627c478bd9Sstevel@tonic-gate mov ttype, %g5 ;\ 8637c478bd9Sstevel@tonic-gate .align 32 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate/* 8667c478bd9Sstevel@tonic-gate * Defaults to BAD entry, but establishes label to be used for 8677c478bd9Sstevel@tonic-gate * architecture-specific overwrite of trap table entry. 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate#define LABELED_BAD(table_name) \ 8707c478bd9Sstevel@tonic-gate .global table_name ;\ 8717c478bd9Sstevel@tonic-gatetable_name: ;\ 8727c478bd9Sstevel@tonic-gate BAD 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate#endif /* !lint */ 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate/* 8777c478bd9Sstevel@tonic-gate * illegal instruction trap 8787c478bd9Sstevel@tonic-gate */ 8797c478bd9Sstevel@tonic-gate#define ILLTRAP_INSTR \ 8807c478bd9Sstevel@tonic-gate membar #Sync ;\ 8817c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8827c478bd9Sstevel@tonic-gate or %g0, P_UTRAP4, %g2 ;\ 8837c478bd9Sstevel@tonic-gate or %g0, T_UNIMP_INSTR, %g3 ;\ 8847c478bd9Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 8857c478bd9Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 8867c478bd9Sstevel@tonic-gate nop ;\ 8877c478bd9Sstevel@tonic-gate .align 32 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate/* 8907c478bd9Sstevel@tonic-gate * tag overflow trap 8917c478bd9Sstevel@tonic-gate */ 8927c478bd9Sstevel@tonic-gate#define TAG_OVERFLOW \ 8937c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8947c478bd9Sstevel@tonic-gate or %g0, P_UTRAP10, %g2 ;\ 8957c478bd9Sstevel@tonic-gate or %g0, T_TAG_OVERFLOW, %g3 ;\ 8967c478bd9Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 8977c478bd9Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 8987c478bd9Sstevel@tonic-gate nop ;\ 8997c478bd9Sstevel@tonic-gate .align 32 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate/* 9027c478bd9Sstevel@tonic-gate * divide by zero trap 9037c478bd9Sstevel@tonic-gate */ 9047c478bd9Sstevel@tonic-gate#define DIV_BY_ZERO \ 9057c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 9067c478bd9Sstevel@tonic-gate or %g0, P_UTRAP11, %g2 ;\ 9077c478bd9Sstevel@tonic-gate or %g0, T_IDIV0, %g3 ;\ 9087c478bd9Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 9097c478bd9Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 9107c478bd9Sstevel@tonic-gate nop ;\ 9117c478bd9Sstevel@tonic-gate .align 32 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate/* 9147c478bd9Sstevel@tonic-gate * trap instruction for V9 user trap handlers 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate#define TRAP_INSTR \ 9177c478bd9Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 9187c478bd9Sstevel@tonic-gate or %g0, T_SOFTWARE_TRAP, %g3 ;\ 9197c478bd9Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 9207c478bd9Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 9217c478bd9Sstevel@tonic-gate nop ;\ 9227c478bd9Sstevel@tonic-gate .align 32 9237c478bd9Sstevel@tonic-gate#define TRP4 TRAP_INSTR; TRAP_INSTR; TRAP_INSTR; TRAP_INSTR 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate/* 9267c478bd9Sstevel@tonic-gate * LEVEL_INTERRUPT is for level N interrupts. 9277c478bd9Sstevel@tonic-gate * VECTOR_INTERRUPT is for the vector trap. 9287c478bd9Sstevel@tonic-gate */ 9297c478bd9Sstevel@tonic-gate#define LEVEL_INTERRUPT(level) \ 9307c478bd9Sstevel@tonic-gate .global tt_pil/**/level ;\ 9317c478bd9Sstevel@tonic-gatett_pil/**/level: ;\ 9327c478bd9Sstevel@tonic-gate ba,pt %xcc, pil_interrupt ;\ 9337c478bd9Sstevel@tonic-gate mov level, %g4 ;\ 9347c478bd9Sstevel@tonic-gate .align 32 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate#define LEVEL14_INTERRUPT \ 9377c478bd9Sstevel@tonic-gate ba pil14_interrupt ;\ 9387c478bd9Sstevel@tonic-gate mov PIL_14, %g4 ;\ 9397c478bd9Sstevel@tonic-gate .align 32 9407c478bd9Sstevel@tonic-gate 941b9e93c10SJonathan Haslam#define LEVEL15_INTERRUPT \ 942b9e93c10SJonathan Haslam ba pil15_interrupt ;\ 943b9e93c10SJonathan Haslam mov PIL_15, %g4 ;\ 944b9e93c10SJonathan Haslam .align 32 945b9e93c10SJonathan Haslam 9467c478bd9Sstevel@tonic-gate#define VECTOR_INTERRUPT \ 9477c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g1 ;\ 9487c478bd9Sstevel@tonic-gate btst IRSR_BUSY, %g1 ;\ 9497c478bd9Sstevel@tonic-gate bnz,pt %xcc, vec_interrupt ;\ 9507c478bd9Sstevel@tonic-gate nop ;\ 9517c478bd9Sstevel@tonic-gate ba,a,pt %xcc, vec_intr_spurious ;\ 9527c478bd9Sstevel@tonic-gate .empty ;\ 9537c478bd9Sstevel@tonic-gate .align 32 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate/* 9567c478bd9Sstevel@tonic-gate * MMU Trap Handlers. 9577c478bd9Sstevel@tonic-gate */ 9587c478bd9Sstevel@tonic-gate#define SWITCH_GLOBALS /* mmu->alt, alt->mmu */ \ 9597c478bd9Sstevel@tonic-gate rdpr %pstate, %g5 ;\ 9607c478bd9Sstevel@tonic-gate wrpr %g5, PSTATE_MG | PSTATE_AG, %pstate 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate#define IMMU_EXCEPTION \ 9637c478bd9Sstevel@tonic-gate membar #Sync ;\ 9647c478bd9Sstevel@tonic-gate SWITCH_GLOBALS ;\ 9657c478bd9Sstevel@tonic-gate wr %g0, ASI_IMMU, %asi ;\ 9667c478bd9Sstevel@tonic-gate rdpr %tpc, %g2 ;\ 9677c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9687c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end ;\ 9697c478bd9Sstevel@tonic-gate mov T_INSTR_EXCEPTION, %g1 ;\ 9707c478bd9Sstevel@tonic-gate .align 32 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate#define DMMU_EXCEPTION \ 9737c478bd9Sstevel@tonic-gate SWITCH_GLOBALS ;\ 9747c478bd9Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 9757c478bd9Sstevel@tonic-gate ldxa [MMU_TAG_ACCESS]%asi, %g2 ;\ 9767c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9777c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end ;\ 9787c478bd9Sstevel@tonic-gate mov T_DATA_EXCEPTION, %g1 ;\ 9797c478bd9Sstevel@tonic-gate .align 32 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate#define DMMU_EXC_AG_PRIV \ 9827c478bd9Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 9837c478bd9Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 9847c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_priv_exception ;\ 9857c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9867c478bd9Sstevel@tonic-gate .align 32 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate#define DMMU_EXC_AG_NOT_ALIGNED \ 9897c478bd9Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 9907c478bd9Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 9917c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 9927c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9937c478bd9Sstevel@tonic-gate .align 32 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate/* 9967c478bd9Sstevel@tonic-gate * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2) 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate#define DMMU_EXC_LDDF_NOT_ALIGNED \ 9997c478bd9Sstevel@tonic-gate btst 1, %sp ;\ 10007c478bd9Sstevel@tonic-gate bnz,pt %xcc, .lddf_exception_not_aligned ;\ 10017c478bd9Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 10027c478bd9Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 10037c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 10047c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 10057c478bd9Sstevel@tonic-gate .align 32 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate#define DMMU_EXC_STDF_NOT_ALIGNED \ 10087c478bd9Sstevel@tonic-gate btst 1, %sp ;\ 10097c478bd9Sstevel@tonic-gate bnz,pt %xcc, .stdf_exception_not_aligned ;\ 10107c478bd9Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 10117c478bd9Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 10127c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 10137c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 10147c478bd9Sstevel@tonic-gate .align 32 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate/* 10177c478bd9Sstevel@tonic-gate * Flush the TLB using either the primary, secondary, or nucleus flush 10187c478bd9Sstevel@tonic-gate * operation based on whether the ctx from the tag access register matches 10197c478bd9Sstevel@tonic-gate * the primary or secondary context (flush the nucleus if neither matches). 10207c478bd9Sstevel@tonic-gate * 10217c478bd9Sstevel@tonic-gate * Requires a membar #Sync before next ld/st. 10227c478bd9Sstevel@tonic-gate * exits with: 10237c478bd9Sstevel@tonic-gate * g2 = tag access register 10247c478bd9Sstevel@tonic-gate * g3 = ctx number 10257c478bd9Sstevel@tonic-gate */ 10267c478bd9Sstevel@tonic-gate#if TAGACC_CTX_MASK != CTXREG_CTX_MASK 10277c478bd9Sstevel@tonic-gate#error "TAGACC_CTX_MASK != CTXREG_CTX_MASK" 10287c478bd9Sstevel@tonic-gate#endif 10297c478bd9Sstevel@tonic-gate#define DTLB_DEMAP_ENTRY \ 10307c478bd9Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g1 ;\ 10317c478bd9Sstevel@tonic-gate mov MMU_PCONTEXT, %g5 ;\ 10327c478bd9Sstevel@tonic-gate ldxa [%g1]ASI_DMMU, %g2 ;\ 10337c478bd9Sstevel@tonic-gate sethi %hi(TAGACC_CTX_MASK), %g4 ;\ 10347c478bd9Sstevel@tonic-gate or %g4, %lo(TAGACC_CTX_MASK), %g4 ;\ 10357c478bd9Sstevel@tonic-gate and %g2, %g4, %g3 /* g3 = ctx */ ;\ 10367c478bd9Sstevel@tonic-gate ldxa [%g5]ASI_DMMU, %g6 /* g6 = primary ctx */ ;\ 10377c478bd9Sstevel@tonic-gate and %g6, %g4, %g6 /* &= CTXREG_CTX_MASK */ ;\ 10387c478bd9Sstevel@tonic-gate cmp %g3, %g6 ;\ 10397c478bd9Sstevel@tonic-gate be,pt %xcc, 1f ;\ 10407c478bd9Sstevel@tonic-gate andn %g2, %g4, %g1 /* ctx = primary */ ;\ 10417c478bd9Sstevel@tonic-gate mov MMU_SCONTEXT, %g5 ;\ 10427c478bd9Sstevel@tonic-gate ldxa [%g5]ASI_DMMU, %g6 /* g6 = secondary ctx */ ;\ 10437c478bd9Sstevel@tonic-gate and %g6, %g4, %g6 /* &= CTXREG_CTX_MASK */ ;\ 10447c478bd9Sstevel@tonic-gate cmp %g3, %g6 ;\ 10457c478bd9Sstevel@tonic-gate be,a,pt %xcc, 1f ;\ 10467c478bd9Sstevel@tonic-gate or %g1, DEMAP_SECOND, %g1 ;\ 10477c478bd9Sstevel@tonic-gate or %g1, DEMAP_NUCLEUS, %g1 ;\ 10487c478bd9Sstevel@tonic-gate1: stxa %g0, [%g1]ASI_DTLB_DEMAP /* MMU_DEMAP_PAGE */ ;\ 10497c478bd9Sstevel@tonic-gate membar #Sync 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate#if defined(cscope) 10527c478bd9Sstevel@tonic-gate/* 10537c478bd9Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that 10547c478bd9Sstevel@tonic-gate * are generated by macro expansion of DTLB_MISS(). 10557c478bd9Sstevel@tonic-gate */ 10567c478bd9Sstevel@tonic-gate .global tt0_dtlbmiss 10577c478bd9Sstevel@tonic-gatett0_dtlbmiss: 10587c478bd9Sstevel@tonic-gate .global tt1_dtlbmiss 10597c478bd9Sstevel@tonic-gatett1_dtlbmiss: 10607c478bd9Sstevel@tonic-gate nop 10617c478bd9Sstevel@tonic-gate#endif 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate/* 10647c478bd9Sstevel@tonic-gate * Needs to be exactly 32 instructions 10657c478bd9Sstevel@tonic-gate * 10667c478bd9Sstevel@tonic-gate * UTLB NOTE: If we don't hit on the 8k pointer then we branch 10677c478bd9Sstevel@tonic-gate * to a special 4M tsb handler. It would be nice if that handler 10687c478bd9Sstevel@tonic-gate * could live in this file but currently it seems better to allow 10697c478bd9Sstevel@tonic-gate * it to fall thru to sfmmu_tsb_miss. 10707c478bd9Sstevel@tonic-gate */ 107125cf1a30Sjl139090#ifdef UTSB_PHYS 107225cf1a30Sjl139090#define DTLB_MISS(table_name) ;\ 107325cf1a30Sjl139090 .global table_name/**/_dtlbmiss ;\ 107425cf1a30Sjl139090table_name/**/_dtlbmiss: ;\ 107525cf1a30Sjl139090 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 107625cf1a30Sjl139090 ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 107725cf1a30Sjl139090 ldxa [%g6]ASI_DMMU, %g2 /* g2 = tag access */ ;\ 107825cf1a30Sjl139090 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 107925cf1a30Sjl139090 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 108025cf1a30Sjl139090 cmp %g3, INVALID_CONTEXT ;\ 108125cf1a30Sjl139090 ble,pn %xcc, sfmmu_kdtlb_miss ;\ 10821426d65aSsm142603 srax %g2, PREDISM_BASESHIFT, %g6 /* g6 > 0 ISM predicted */ ;\ 10831426d65aSsm142603 brgz,pn %g6, sfmmu_udtlb_slowpath_ismpred ;\ 108425cf1a30Sjl139090 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 108525cf1a30Sjl139090 ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, %g5 data */;\ 108625cf1a30Sjl139090 cmp %g4, %g7 ;\ 10871426d65aSsm142603 bne,pn %xcc, sfmmu_udtlb_slowpath_noismpred ;\ 10881426d65aSsm142603 nop ;\ 108925cf1a30Sjl139090 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 109025cf1a30Sjl139090 stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\ 109125cf1a30Sjl139090 retry /* in %g5 */ ;\ 109225cf1a30Sjl139090 unimp 0 ;\ 109325cf1a30Sjl139090 unimp 0 ;\ 109425cf1a30Sjl139090 unimp 0 ;\ 109525cf1a30Sjl139090 unimp 0 ;\ 109625cf1a30Sjl139090 unimp 0 ;\ 109725cf1a30Sjl139090 unimp 0 ;\ 109825cf1a30Sjl139090 unimp 0 ;\ 109925cf1a30Sjl139090 unimp 0 ;\ 110025cf1a30Sjl139090 unimp 0 ;\ 110105d3dc4bSpaulsan unimp 0 ;\ 110205d3dc4bSpaulsan unimp 0 ;\ 110305d3dc4bSpaulsan unimp 0 ;\ 11041426d65aSsm142603 unimp 0 ;\ 11051426d65aSsm142603 unimp 0 ;\ 110625cf1a30Sjl139090 .align 128 11071426d65aSsm142603 110825cf1a30Sjl139090#else /* UTSB_PHYS */ 11097c478bd9Sstevel@tonic-gate#define DTLB_MISS(table_name) ;\ 11107c478bd9Sstevel@tonic-gate .global table_name/**/_dtlbmiss ;\ 11117c478bd9Sstevel@tonic-gatetable_name/**/_dtlbmiss: ;\ 11127c478bd9Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 11137c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 11147c478bd9Sstevel@tonic-gate ldxa [%g6]ASI_DMMU, %g2 /* g2 = tag access */ ;\ 11157c478bd9Sstevel@tonic-gate sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 11167c478bd9Sstevel@tonic-gate srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 11177c478bd9Sstevel@tonic-gate cmp %g3, INVALID_CONTEXT ;\ 11187c478bd9Sstevel@tonic-gate ble,pn %xcc, sfmmu_kdtlb_miss ;\ 11197c478bd9Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 11207c478bd9Sstevel@tonic-gate brlz,pn %g1, sfmmu_udtlb_slowpath ;\ 11217c478bd9Sstevel@tonic-gate nop ;\ 11227c478bd9Sstevel@tonic-gate ldda [%g1]ASI_NQUAD_LD, %g4 /* g4 = tag, %g5 data */ ;\ 11237c478bd9Sstevel@tonic-gate cmp %g4, %g7 ;\ 11247c478bd9Sstevel@tonic-gate bne,pn %xcc, sfmmu_tsb_miss_tt /* no 4M TSB, miss */ ;\ 112505d3dc4bSpaulsan mov -1, %g3 /* set 4M tsbe ptr to -1 */ ;\ 11267c478bd9Sstevel@tonic-gate TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 11277c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\ 11287c478bd9Sstevel@tonic-gate retry /* in %g5 */ ;\ 11297c478bd9Sstevel@tonic-gate unimp 0 ;\ 11307c478bd9Sstevel@tonic-gate unimp 0 ;\ 11317c478bd9Sstevel@tonic-gate unimp 0 ;\ 11327c478bd9Sstevel@tonic-gate unimp 0 ;\ 11337c478bd9Sstevel@tonic-gate unimp 0 ;\ 11347c478bd9Sstevel@tonic-gate unimp 0 ;\ 11357c478bd9Sstevel@tonic-gate unimp 0 ;\ 11367c478bd9Sstevel@tonic-gate unimp 0 ;\ 11377c478bd9Sstevel@tonic-gate unimp 0 ;\ 11387c478bd9Sstevel@tonic-gate unimp 0 ;\ 11397c478bd9Sstevel@tonic-gate unimp 0 ;\ 114005d3dc4bSpaulsan unimp 0 ;\ 114105d3dc4bSpaulsan unimp 0 ;\ 114205d3dc4bSpaulsan unimp 0 ;\ 11437c478bd9Sstevel@tonic-gate .align 128 114425cf1a30Sjl139090#endif /* UTSB_PHYS */ 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate#if defined(cscope) 11477c478bd9Sstevel@tonic-gate/* 11487c478bd9Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that 11497c478bd9Sstevel@tonic-gate * are generated by macro expansion of ITLB_MISS(). 11507c478bd9Sstevel@tonic-gate */ 11517c478bd9Sstevel@tonic-gate .global tt0_itlbmiss 11527c478bd9Sstevel@tonic-gatett0_itlbmiss: 11537c478bd9Sstevel@tonic-gate .global tt1_itlbmiss 11547c478bd9Sstevel@tonic-gatett1_itlbmiss: 11557c478bd9Sstevel@tonic-gate nop 11567c478bd9Sstevel@tonic-gate#endif 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate/* 11597c478bd9Sstevel@tonic-gate * Instruction miss handler. 11607c478bd9Sstevel@tonic-gate * ldda instructions will have their ASI patched 11617c478bd9Sstevel@tonic-gate * by sfmmu_patch_ktsb at runtime. 11627c478bd9Sstevel@tonic-gate * MUST be EXACTLY 32 instructions or we'll break. 11637c478bd9Sstevel@tonic-gate */ 116425cf1a30Sjl139090#ifdef UTSB_PHYS 116525cf1a30Sjl139090#define ITLB_MISS(table_name) \ 116625cf1a30Sjl139090 .global table_name/**/_itlbmiss ;\ 116725cf1a30Sjl139090table_name/**/_itlbmiss: ;\ 116825cf1a30Sjl139090 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 116925cf1a30Sjl139090 ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 117025cf1a30Sjl139090 ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\ 117125cf1a30Sjl139090 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 117225cf1a30Sjl139090 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 117325cf1a30Sjl139090 cmp %g3, INVALID_CONTEXT ;\ 117425cf1a30Sjl139090 ble,pn %xcc, sfmmu_kitlb_miss ;\ 117525cf1a30Sjl139090 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 117625cf1a30Sjl139090 ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ 117725cf1a30Sjl139090 cmp %g4, %g7 ;\ 11781426d65aSsm142603 bne,pn %xcc, sfmmu_uitlb_slowpath ;\ 117925cf1a30Sjl139090 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 118025cf1a30Sjl139090 bz,pn %icc, exec_fault ;\ 118125cf1a30Sjl139090 nop ;\ 118225cf1a30Sjl139090 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 118325cf1a30Sjl139090 stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\ 118425cf1a30Sjl139090 retry ;\ 118525cf1a30Sjl139090 unimp 0 ;\ 118625cf1a30Sjl139090 unimp 0 ;\ 118725cf1a30Sjl139090 unimp 0 ;\ 118825cf1a30Sjl139090 unimp 0 ;\ 118925cf1a30Sjl139090 unimp 0 ;\ 119025cf1a30Sjl139090 unimp 0 ;\ 119105d3dc4bSpaulsan unimp 0 ;\ 119205d3dc4bSpaulsan unimp 0 ;\ 119305d3dc4bSpaulsan unimp 0 ;\ 11941426d65aSsm142603 unimp 0 ;\ 11951426d65aSsm142603 unimp 0 ;\ 11961426d65aSsm142603 unimp 0 ;\ 11971426d65aSsm142603 unimp 0 ;\ 11981426d65aSsm142603 unimp 0 ;\ 119925cf1a30Sjl139090 .align 128 12001426d65aSsm142603 120125cf1a30Sjl139090#else /* UTSB_PHYS */ 12027c478bd9Sstevel@tonic-gate#define ITLB_MISS(table_name) \ 12037c478bd9Sstevel@tonic-gate .global table_name/**/_itlbmiss ;\ 12047c478bd9Sstevel@tonic-gatetable_name/**/_itlbmiss: ;\ 12057c478bd9Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 12067c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 12077c478bd9Sstevel@tonic-gate ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\ 12087c478bd9Sstevel@tonic-gate sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 12097c478bd9Sstevel@tonic-gate srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 12107c478bd9Sstevel@tonic-gate cmp %g3, INVALID_CONTEXT ;\ 12117c478bd9Sstevel@tonic-gate ble,pn %xcc, sfmmu_kitlb_miss ;\ 12127c478bd9Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 12137c478bd9Sstevel@tonic-gate brlz,pn %g1, sfmmu_uitlb_slowpath /* if >1 TSB branch */ ;\ 12147c478bd9Sstevel@tonic-gate nop ;\ 12157c478bd9Sstevel@tonic-gate ldda [%g1]ASI_NQUAD_LD, %g4 /* g4 = tag, g5 = data */ ;\ 12167c478bd9Sstevel@tonic-gate cmp %g4, %g7 ;\ 12177c478bd9Sstevel@tonic-gate bne,pn %xcc, sfmmu_tsb_miss_tt /* br if 8k ptr miss */ ;\ 121805d3dc4bSpaulsan mov -1, %g3 /* set 4M TSB ptr to -1 */ ;\ 12197c478bd9Sstevel@tonic-gate andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 12207c478bd9Sstevel@tonic-gate bz,pn %icc, exec_fault ;\ 12217c478bd9Sstevel@tonic-gate nop ;\ 12227c478bd9Sstevel@tonic-gate TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 12237c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\ 12247c478bd9Sstevel@tonic-gate retry ;\ 12257c478bd9Sstevel@tonic-gate unimp 0 ;\ 12267c478bd9Sstevel@tonic-gate unimp 0 ;\ 12277c478bd9Sstevel@tonic-gate unimp 0 ;\ 12287c478bd9Sstevel@tonic-gate unimp 0 ;\ 12297c478bd9Sstevel@tonic-gate unimp 0 ;\ 12307c478bd9Sstevel@tonic-gate unimp 0 ;\ 12317c478bd9Sstevel@tonic-gate unimp 0 ;\ 12327c478bd9Sstevel@tonic-gate unimp 0 ;\ 123305d3dc4bSpaulsan unimp 0 ;\ 123405d3dc4bSpaulsan unimp 0 ;\ 123505d3dc4bSpaulsan unimp 0 ;\ 12367c478bd9Sstevel@tonic-gate .align 128 123725cf1a30Sjl139090#endif /* UTSB_PHYS */ 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate/* 12417c478bd9Sstevel@tonic-gate * This macro is the first level handler for fast protection faults. 12427c478bd9Sstevel@tonic-gate * It first demaps the tlb entry which generated the fault and then 12437c478bd9Sstevel@tonic-gate * attempts to set the modify bit on the hash. It needs to be 12447c478bd9Sstevel@tonic-gate * exactly 32 instructions. 12457c478bd9Sstevel@tonic-gate */ 12467c478bd9Sstevel@tonic-gate#define DTLB_PROT \ 12477c478bd9Sstevel@tonic-gate DTLB_DEMAP_ENTRY /* 20 instructions */ ;\ 12487c478bd9Sstevel@tonic-gate /* ;\ 12497c478bd9Sstevel@tonic-gate * At this point: ;\ 12507c478bd9Sstevel@tonic-gate * g1 = ???? ;\ 12517c478bd9Sstevel@tonic-gate * g2 = tag access register ;\ 12527c478bd9Sstevel@tonic-gate * g3 = ctx number ;\ 12537c478bd9Sstevel@tonic-gate * g4 = ???? ;\ 12547c478bd9Sstevel@tonic-gate */ ;\ 12557c478bd9Sstevel@tonic-gate TT_TRACE(trace_dataprot) /* 2 instr ifdef TRAPTRACE */ ;\ 12567c478bd9Sstevel@tonic-gate /* clobbers g1 and g6 */ ;\ 12577c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 12587c478bd9Sstevel@tonic-gate brnz,pt %g3, sfmmu_uprot_trap /* user trap */ ;\ 12597c478bd9Sstevel@tonic-gate nop ;\ 12607c478bd9Sstevel@tonic-gate ba,a,pt %xcc, sfmmu_kprot_trap /* kernel trap */ ;\ 12617c478bd9Sstevel@tonic-gate unimp 0 ;\ 12627c478bd9Sstevel@tonic-gate unimp 0 ;\ 12637c478bd9Sstevel@tonic-gate unimp 0 ;\ 12647c478bd9Sstevel@tonic-gate unimp 0 ;\ 12657c478bd9Sstevel@tonic-gate unimp 0 ;\ 12667c478bd9Sstevel@tonic-gate unimp 0 ;\ 12677c478bd9Sstevel@tonic-gate .align 128 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate#define DMMU_EXCEPTION_TL1 ;\ 12707c478bd9Sstevel@tonic-gate SWITCH_GLOBALS ;\ 12717c478bd9Sstevel@tonic-gate ba,a,pt %xcc, mmu_trap_tl1 ;\ 12727c478bd9Sstevel@tonic-gate nop ;\ 12737c478bd9Sstevel@tonic-gate .align 32 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate#define MISALIGN_ADDR_TL1 ;\ 12767c478bd9Sstevel@tonic-gate ba,a,pt %xcc, mmu_trap_tl1 ;\ 12777c478bd9Sstevel@tonic-gate nop ;\ 12787c478bd9Sstevel@tonic-gate .align 32 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate/* 12817c478bd9Sstevel@tonic-gate * Trace a tsb hit 12827c478bd9Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 12837c478bd9Sstevel@tonic-gate * g2 = tag access register (in) 12847c478bd9Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 12857c478bd9Sstevel@tonic-gate * g5 = tsbe data (in) 12867c478bd9Sstevel@tonic-gate * g6 = scratch (clobbered) 12877c478bd9Sstevel@tonic-gate * g7 = pc we jumped here from (in) 12887c478bd9Sstevel@tonic-gate * ttextra = value to OR in to trap type (%tt) (in) 12897c478bd9Sstevel@tonic-gate */ 12907c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 12917c478bd9Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra) \ 12927c478bd9Sstevel@tonic-gate membar #Sync ;\ 12937c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 ;\ 12947c478bd9Sstevel@tonic-gate flush %g6 ;\ 12957c478bd9Sstevel@tonic-gate TRACE_PTR(%g3, %g6) ;\ 1296*023e71deSHaik Aftandilian GET_TRACE_TICK(%g6, %g4) ;\ 12977c478bd9Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi ;\ 12987c478bd9Sstevel@tonic-gate stxa %g2, [%g3 + TRAP_ENT_SP]%asi /* tag access */ ;\ 12997c478bd9Sstevel@tonic-gate stxa %g5, [%g3 + TRAP_ENT_F1]%asi /* tsb data */ ;\ 13007c478bd9Sstevel@tonic-gate rdpr %tnpc, %g6 ;\ 13017c478bd9Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_F2]%asi ;\ 13027c478bd9Sstevel@tonic-gate stxa %g1, [%g3 + TRAP_ENT_F3]%asi /* tsb pointer */ ;\ 13037c478bd9Sstevel@tonic-gate stxa %g0, [%g3 + TRAP_ENT_F4]%asi ;\ 13047c478bd9Sstevel@tonic-gate rdpr %tpc, %g6 ;\ 13057c478bd9Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TPC]%asi ;\ 13067c478bd9Sstevel@tonic-gate rdpr %tl, %g6 ;\ 13077c478bd9Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TL]%asi ;\ 13087c478bd9Sstevel@tonic-gate rdpr %tt, %g6 ;\ 13097c478bd9Sstevel@tonic-gate or %g6, (ttextra), %g6 ;\ 13107c478bd9Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi ;\ 13117c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_IMMU, %g1 /* tag target */ ;\ 13127c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DMMU, %g4 ;\ 13137c478bd9Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT ;\ 13147c478bd9Sstevel@tonic-gate movne %icc, %g4, %g1 ;\ 13157c478bd9Sstevel@tonic-gate stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tsb tag */ ;\ 13167c478bd9Sstevel@tonic-gate stxa %g0, [%g3 + TRAP_ENT_TR]%asi ;\ 13177c478bd9Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g6) 13187c478bd9Sstevel@tonic-gate#else 13197c478bd9Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra) 13207c478bd9Sstevel@tonic-gate#endif 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate#if defined(lint) 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gatestruct scb trap_table; 13257c478bd9Sstevel@tonic-gatestruct scb scb; /* trap_table/scb are the same object */ 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate#else /* lint */ 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate/* 13307c478bd9Sstevel@tonic-gate * ======================================================================= 13317c478bd9Sstevel@tonic-gate * SPARC V9 TRAP TABLE 13327c478bd9Sstevel@tonic-gate * 13337c478bd9Sstevel@tonic-gate * The trap table is divided into two halves: the first half is used when 13347c478bd9Sstevel@tonic-gate * taking traps when TL=0; the second half is used when taking traps from 13357c478bd9Sstevel@tonic-gate * TL>0. Note that handlers in the second half of the table might not be able 13367c478bd9Sstevel@tonic-gate * to make the same assumptions as handlers in the first half of the table. 13377c478bd9Sstevel@tonic-gate * 13387c478bd9Sstevel@tonic-gate * Worst case trap nesting so far: 13397c478bd9Sstevel@tonic-gate * 13407c478bd9Sstevel@tonic-gate * at TL=0 client issues software trap requesting service 13417c478bd9Sstevel@tonic-gate * at TL=1 nucleus wants a register window 13427c478bd9Sstevel@tonic-gate * at TL=2 register window clean/spill/fill takes a TLB miss 13437c478bd9Sstevel@tonic-gate * at TL=3 processing TLB miss 13447c478bd9Sstevel@tonic-gate * at TL=4 handle asynchronous error 13457c478bd9Sstevel@tonic-gate * 13467c478bd9Sstevel@tonic-gate * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode". 13477c478bd9Sstevel@tonic-gate * 13487c478bd9Sstevel@tonic-gate * ======================================================================= 13497c478bd9Sstevel@tonic-gate */ 13507c478bd9Sstevel@tonic-gate .section ".text" 13517c478bd9Sstevel@tonic-gate .align 4 13527c478bd9Sstevel@tonic-gate .global trap_table, scb, trap_table0, trap_table1, etrap_table 135341f63f87Spetede .type trap_table, #object 135441f63f87Spetede .type scb, #object 13557c478bd9Sstevel@tonic-gatetrap_table: 13567c478bd9Sstevel@tonic-gatescb: 13577c478bd9Sstevel@tonic-gatetrap_table0: 13587c478bd9Sstevel@tonic-gate /* hardware traps */ 13597c478bd9Sstevel@tonic-gate NOT; /* 000 reserved */ 13607c478bd9Sstevel@tonic-gate RED; /* 001 power on reset */ 13617c478bd9Sstevel@tonic-gate RED; /* 002 watchdog reset */ 13627c478bd9Sstevel@tonic-gate RED; /* 003 externally initiated reset */ 13637c478bd9Sstevel@tonic-gate RED; /* 004 software initiated reset */ 13647c478bd9Sstevel@tonic-gate RED; /* 005 red mode exception */ 13657c478bd9Sstevel@tonic-gate NOT; NOT; /* 006 - 007 reserved */ 13667c478bd9Sstevel@tonic-gate IMMU_EXCEPTION; /* 008 instruction access exception */ 13677c478bd9Sstevel@tonic-gate NOT; /* 009 instruction access MMU miss */ 136825cf1a30Sjl139090 ASYNC_TRAP(T_INSTR_ERROR, trace_gen, tt0_iae); 13697c478bd9Sstevel@tonic-gate /* 00A instruction access error */ 13707c478bd9Sstevel@tonic-gate NOT; NOT4; /* 00B - 00F reserved */ 13717c478bd9Sstevel@tonic-gate ILLTRAP_INSTR; /* 010 illegal instruction */ 13727c478bd9Sstevel@tonic-gate TRAP(T_PRIV_INSTR); /* 011 privileged opcode */ 13737c478bd9Sstevel@tonic-gate NOT; /* 012 unimplemented LDD */ 13747c478bd9Sstevel@tonic-gate NOT; /* 013 unimplemented STD */ 13757c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 014 - 01F reserved */ 13767c478bd9Sstevel@tonic-gate FP_DISABLED_TRAP; /* 020 fp disabled */ 13777c478bd9Sstevel@tonic-gate FP_IEEE_TRAP; /* 021 fp exception ieee 754 */ 13787c478bd9Sstevel@tonic-gate FP_TRAP; /* 022 fp exception other */ 13797c478bd9Sstevel@tonic-gate TAG_OVERFLOW; /* 023 tag overflow */ 13807c478bd9Sstevel@tonic-gate CLEAN_WINDOW; /* 024 - 027 clean window */ 13817c478bd9Sstevel@tonic-gate DIV_BY_ZERO; /* 028 division by zero */ 13827c478bd9Sstevel@tonic-gate NOT; /* 029 internal processor error */ 13837c478bd9Sstevel@tonic-gate NOT; NOT; NOT4; /* 02A - 02F reserved */ 13847c478bd9Sstevel@tonic-gate DMMU_EXCEPTION; /* 030 data access exception */ 13857c478bd9Sstevel@tonic-gate NOT; /* 031 data access MMU miss */ 138625cf1a30Sjl139090 ASYNC_TRAP(T_DATA_ERROR, trace_gen, tt0_dae); 13877c478bd9Sstevel@tonic-gate /* 032 data access error */ 13887c478bd9Sstevel@tonic-gate NOT; /* 033 data access protection */ 13897c478bd9Sstevel@tonic-gate DMMU_EXC_AG_NOT_ALIGNED; /* 034 mem address not aligned */ 13907c478bd9Sstevel@tonic-gate DMMU_EXC_LDDF_NOT_ALIGNED; /* 035 LDDF mem address not aligned */ 13917c478bd9Sstevel@tonic-gate DMMU_EXC_STDF_NOT_ALIGNED; /* 036 STDF mem address not aligned */ 13927c478bd9Sstevel@tonic-gate DMMU_EXC_AG_PRIV; /* 037 privileged action */ 13937c478bd9Sstevel@tonic-gate NOT; /* 038 LDQF mem address not aligned */ 13947c478bd9Sstevel@tonic-gate NOT; /* 039 STQF mem address not aligned */ 13957c478bd9Sstevel@tonic-gate NOT; NOT; NOT4; /* 03A - 03F reserved */ 139625cf1a30Sjl139090 LABELED_BAD(tt0_asdat); /* 040 async data error */ 13977c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(1); /* 041 interrupt level 1 */ 13987c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(2); /* 042 interrupt level 2 */ 13997c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(3); /* 043 interrupt level 3 */ 14007c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(4); /* 044 interrupt level 4 */ 14017c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(5); /* 045 interrupt level 5 */ 14027c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(6); /* 046 interrupt level 6 */ 14037c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(7); /* 047 interrupt level 7 */ 14047c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(8); /* 048 interrupt level 8 */ 14057c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(9); /* 049 interrupt level 9 */ 14067c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(10); /* 04A interrupt level 10 */ 14077c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(11); /* 04B interrupt level 11 */ 14087c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(12); /* 04C interrupt level 12 */ 14097c478bd9Sstevel@tonic-gate LEVEL_INTERRUPT(13); /* 04D interrupt level 13 */ 14107c478bd9Sstevel@tonic-gate LEVEL14_INTERRUPT; /* 04E interrupt level 14 */ 1411b9e93c10SJonathan Haslam LEVEL15_INTERRUPT; /* 04F interrupt level 15 */ 14127c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 050 - 05F reserved */ 14137c478bd9Sstevel@tonic-gate VECTOR_INTERRUPT; /* 060 interrupt vector */ 14147c478bd9Sstevel@tonic-gate GOTO(kmdb_trap); /* 061 PA watchpoint */ 14157c478bd9Sstevel@tonic-gate GOTO(kmdb_trap); /* 062 VA watchpoint */ 14167c478bd9Sstevel@tonic-gate GOTO_TT(ce_err, trace_gen); /* 063 corrected ECC error */ 14177c478bd9Sstevel@tonic-gate ITLB_MISS(tt0); /* 064 instruction access MMU miss */ 14187c478bd9Sstevel@tonic-gate DTLB_MISS(tt0); /* 068 data access MMU miss */ 14197c478bd9Sstevel@tonic-gate DTLB_PROT; /* 06C data access protection */ 14207c478bd9Sstevel@tonic-gate LABELED_BAD(tt0_fecc); /* 070 fast ecache ECC error */ 14217c478bd9Sstevel@tonic-gate LABELED_BAD(tt0_dperr); /* 071 Cheetah+ dcache parity error */ 14227c478bd9Sstevel@tonic-gate LABELED_BAD(tt0_iperr); /* 072 Cheetah+ icache parity error */ 14237c478bd9Sstevel@tonic-gate NOT; /* 073 reserved */ 14247c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 074 - 07F reserved */ 14257c478bd9Sstevel@tonic-gate NOT4; /* 080 spill 0 normal */ 14267c478bd9Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUP,sn0); /* 084 spill 1 normal */ 14277c478bd9Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUP,sn0); /* 088 spill 2 normal */ 14287c478bd9Sstevel@tonic-gate SPILL_32clean(ASI_AIUP,sn0); /* 08C spill 3 normal */ 14297c478bd9Sstevel@tonic-gate SPILL_64clean(ASI_AIUP,sn0); /* 090 spill 4 normal */ 14307c478bd9Sstevel@tonic-gate SPILL_32bit(not); /* 094 spill 5 normal */ 14317c478bd9Sstevel@tonic-gate SPILL_64bit(not); /* 098 spill 6 normal */ 14327c478bd9Sstevel@tonic-gate SPILL_mixed; /* 09C spill 7 normal */ 14337c478bd9Sstevel@tonic-gate NOT4; /* 0A0 spill 0 other */ 14347c478bd9Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUS,so0); /* 0A4 spill 1 other */ 14357c478bd9Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUS,so0); /* 0A8 spill 2 other */ 14367c478bd9Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUS,so0); /* 0AC spill 3 other */ 14377c478bd9Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUS,so0); /* 0B0 spill 4 other */ 14387c478bd9Sstevel@tonic-gate NOT4; /* 0B4 spill 5 other */ 14397c478bd9Sstevel@tonic-gate NOT4; /* 0B8 spill 6 other */ 14407c478bd9Sstevel@tonic-gate NOT4; /* 0BC spill 7 other */ 14417c478bd9Sstevel@tonic-gate NOT4; /* 0C0 fill 0 normal */ 14427c478bd9Sstevel@tonic-gate FILL_32bit_asi(ASI_AIUP,fn0); /* 0C4 fill 1 normal */ 14437c478bd9Sstevel@tonic-gate FILL_64bit_asi(ASI_AIUP,fn0); /* 0C8 fill 2 normal */ 14447c478bd9Sstevel@tonic-gate FILL_32bit_asi(ASI_AIUP,fn0); /* 0CC fill 3 normal */ 14457c478bd9Sstevel@tonic-gate FILL_64bit_asi(ASI_AIUP,fn0); /* 0D0 fill 4 normal */ 14467c478bd9Sstevel@tonic-gate FILL_32bit(not); /* 0D4 fill 5 normal */ 14477c478bd9Sstevel@tonic-gate FILL_64bit(not); /* 0D8 fill 6 normal */ 14487c478bd9Sstevel@tonic-gate FILL_mixed; /* 0DC fill 7 normal */ 14497c478bd9Sstevel@tonic-gate NOT4; /* 0E0 fill 0 other */ 14507c478bd9Sstevel@tonic-gate NOT4; /* 0E4 fill 1 other */ 14517c478bd9Sstevel@tonic-gate NOT4; /* 0E8 fill 2 other */ 14527c478bd9Sstevel@tonic-gate NOT4; /* 0EC fill 3 other */ 14537c478bd9Sstevel@tonic-gate NOT4; /* 0F0 fill 4 other */ 14547c478bd9Sstevel@tonic-gate NOT4; /* 0F4 fill 5 other */ 14557c478bd9Sstevel@tonic-gate NOT4; /* 0F8 fill 6 other */ 14567c478bd9Sstevel@tonic-gate NOT4; /* 0FC fill 7 other */ 14577c478bd9Sstevel@tonic-gate /* user traps */ 14587c478bd9Sstevel@tonic-gate GOTO(syscall_trap_4x); /* 100 old system call */ 14597c478bd9Sstevel@tonic-gate TRAP(T_BREAKPOINT); /* 101 user breakpoint */ 14607c478bd9Sstevel@tonic-gate TRAP(T_DIV0); /* 102 user divide by zero */ 146150eff769Smb158278 FLUSHW(tt0_flushw); /* 103 flush windows */ 14627c478bd9Sstevel@tonic-gate GOTO(.clean_windows); /* 104 clean windows */ 14637c478bd9Sstevel@tonic-gate BAD; /* 105 range check ?? */ 14647c478bd9Sstevel@tonic-gate GOTO(.fix_alignment); /* 106 do unaligned references */ 14657c478bd9Sstevel@tonic-gate BAD; /* 107 unused */ 146659f2ff5cSedp SYSCALL_TRAP32; /* 108 ILP32 system call on LP64 */ 14677c478bd9Sstevel@tonic-gate GOTO(set_trap0_addr); /* 109 set trap0 address */ 14687c478bd9Sstevel@tonic-gate BAD; BAD; BAD4; /* 10A - 10F unused */ 14697c478bd9Sstevel@tonic-gate TRP4; TRP4; TRP4; TRP4; /* 110 - 11F V9 user trap handlers */ 14707c478bd9Sstevel@tonic-gate GOTO(.getcc); /* 120 get condition codes */ 14717c478bd9Sstevel@tonic-gate GOTO(.setcc); /* 121 set condition codes */ 14727c478bd9Sstevel@tonic-gate GOTO(.getpsr); /* 122 get psr */ 14737c478bd9Sstevel@tonic-gate GOTO(.setpsr); /* 123 set psr (some fields) */ 14747c478bd9Sstevel@tonic-gate GOTO(get_timestamp); /* 124 get timestamp */ 14757c478bd9Sstevel@tonic-gate GOTO(get_virtime); /* 125 get lwp virtual time */ 14767c478bd9Sstevel@tonic-gate PRIV(self_xcall); /* 126 self xcall */ 14777c478bd9Sstevel@tonic-gate GOTO(get_hrestime); /* 127 get hrestime */ 14787c478bd9Sstevel@tonic-gate BAD; /* 128 ST_SETV9STACK */ 14797c478bd9Sstevel@tonic-gate GOTO(.getlgrp); /* 129 get lgrpid */ 14807c478bd9Sstevel@tonic-gate BAD; BAD; BAD4; /* 12A - 12F unused */ 14817c478bd9Sstevel@tonic-gate BAD4; BAD4; /* 130 - 137 unused */ 14827c478bd9Sstevel@tonic-gate DTRACE_PID; /* 138 dtrace pid tracing provider */ 1483f498645aSahl BAD; /* 139 unused */ 14847c478bd9Sstevel@tonic-gate DTRACE_RETURN; /* 13A dtrace pid return probe */ 14857c478bd9Sstevel@tonic-gate BAD; BAD4; /* 13B - 13F unused */ 148659f2ff5cSedp SYSCALL_TRAP; /* 140 LP64 system call */ 1487af3c157aSrscott SYSCALL(nosys); /* 141 unused system call trap */ 14887c478bd9Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL 14897c478bd9Sstevel@tonic-gate GOTO(.traptrace_freeze); /* 142 freeze traptrace */ 14907c478bd9Sstevel@tonic-gate GOTO(.traptrace_unfreeze); /* 143 unfreeze traptrace */ 14917c478bd9Sstevel@tonic-gate#else 1492af3c157aSrscott SYSCALL(nosys); /* 142 unused system call trap */ 1493af3c157aSrscott SYSCALL(nosys); /* 143 unused system call trap */ 14947c478bd9Sstevel@tonic-gate#endif 14957c478bd9Sstevel@tonic-gate BAD4; BAD4; BAD4; /* 144 - 14F unused */ 14967c478bd9Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 150 - 15F unused */ 14977c478bd9Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 160 - 16F unused */ 14987c478bd9Sstevel@tonic-gate BAD; /* 170 - unused */ 14997c478bd9Sstevel@tonic-gate BAD; /* 171 - unused */ 15007c478bd9Sstevel@tonic-gate BAD; BAD; /* 172 - 173 unused */ 15017c478bd9Sstevel@tonic-gate BAD4; BAD4; /* 174 - 17B unused */ 15027c478bd9Sstevel@tonic-gate#ifdef PTL1_PANIC_DEBUG 15037c478bd9Sstevel@tonic-gate mov PTL1_BAD_DEBUG, %g1; GOTO(ptl1_panic); 15047c478bd9Sstevel@tonic-gate /* 17C test ptl1_panic */ 15057c478bd9Sstevel@tonic-gate#else 15067c478bd9Sstevel@tonic-gate BAD; /* 17C unused */ 15077c478bd9Sstevel@tonic-gate#endif /* PTL1_PANIC_DEBUG */ 15087c478bd9Sstevel@tonic-gate PRIV(kmdb_trap); /* 17D kmdb enter (L1-A) */ 15097c478bd9Sstevel@tonic-gate PRIV(kmdb_trap); /* 17E kmdb breakpoint */ 15107c478bd9Sstevel@tonic-gate PRIV(kctx_obp_bpt); /* 17F obp breakpoint */ 15117c478bd9Sstevel@tonic-gate /* reserved */ 15127c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 180 - 18F reserved */ 15137c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 190 - 19F reserved */ 15147c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1A0 - 1AF reserved */ 15157c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1B0 - 1BF reserved */ 15167c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1C0 - 1CF reserved */ 15177c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1D0 - 1DF reserved */ 15187c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1E0 - 1EF reserved */ 15197c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1F0 - 1FF reserved */ 15207c478bd9Sstevel@tonic-gatetrap_table1: 15217c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT; NOT; /* 000 - 009 unused */ 152225cf1a30Sjl139090 ASYNC_TRAP(T_INSTR_ERROR + T_TL1, trace_gen, tt1_iae); 15237c478bd9Sstevel@tonic-gate /* 00A instruction access error */ 15247c478bd9Sstevel@tonic-gate NOT; NOT4; /* 00B - 00F unused */ 15257c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 010 - 01F unused */ 15267c478bd9Sstevel@tonic-gate NOT4; /* 020 - 023 unused */ 15277c478bd9Sstevel@tonic-gate CLEAN_WINDOW; /* 024 - 027 clean window */ 15287c478bd9Sstevel@tonic-gate NOT4; NOT4; /* 028 - 02F unused */ 15297c478bd9Sstevel@tonic-gate DMMU_EXCEPTION_TL1; /* 030 data access exception */ 15307c478bd9Sstevel@tonic-gate NOT; /* 031 unused */ 153125cf1a30Sjl139090 ASYNC_TRAP(T_DATA_ERROR + T_TL1, trace_gen, tt1_dae); 15327c478bd9Sstevel@tonic-gate /* 032 data access error */ 15337c478bd9Sstevel@tonic-gate NOT; /* 033 unused */ 15347c478bd9Sstevel@tonic-gate MISALIGN_ADDR_TL1; /* 034 mem address not aligned */ 15357c478bd9Sstevel@tonic-gate NOT; NOT; NOT; NOT4; NOT4 /* 035 - 03F unused */ 153625cf1a30Sjl139090 LABELED_BAD(tt1_asdat); /* 040 async data error */ 153725cf1a30Sjl139090 NOT; NOT; NOT; /* 041 - 043 unused */ 153825cf1a30Sjl139090 NOT4; NOT4; NOT4; /* 044 - 04F unused */ 15397c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 050 - 05F unused */ 15407c478bd9Sstevel@tonic-gate NOT; /* 060 unused */ 15417c478bd9Sstevel@tonic-gate GOTO(kmdb_trap_tl1); /* 061 PA watchpoint */ 15427c478bd9Sstevel@tonic-gate GOTO(kmdb_trap_tl1); /* 062 VA watchpoint */ 15437c478bd9Sstevel@tonic-gate GOTO_TT(ce_err_tl1, trace_gen); /* 063 corrected ECC error */ 15447c478bd9Sstevel@tonic-gate ITLB_MISS(tt1); /* 064 instruction access MMU miss */ 15457c478bd9Sstevel@tonic-gate DTLB_MISS(tt1); /* 068 data access MMU miss */ 15467c478bd9Sstevel@tonic-gate DTLB_PROT; /* 06C data access protection */ 15477c478bd9Sstevel@tonic-gate LABELED_BAD(tt1_fecc); /* 070 fast ecache ECC error */ 15487c478bd9Sstevel@tonic-gate LABELED_BAD(tt1_dperr); /* 071 Cheetah+ dcache parity error */ 15497c478bd9Sstevel@tonic-gate LABELED_BAD(tt1_iperr); /* 072 Cheetah+ icache parity error */ 15507c478bd9Sstevel@tonic-gate NOT; /* 073 reserved */ 15517c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 074 - 07F reserved */ 15527c478bd9Sstevel@tonic-gate NOT4; /* 080 spill 0 normal */ 15537c478bd9Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUP,sn1); /* 084 spill 1 normal */ 15547c478bd9Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUP,sn1); /* 088 spill 2 normal */ 15557c478bd9Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUP,sn1); /* 08C spill 3 normal */ 15567c478bd9Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUP,sn1); /* 090 spill 4 normal */ 15577c478bd9Sstevel@tonic-gate SPILL_32bit(not); /* 094 spill 5 normal */ 15587c478bd9Sstevel@tonic-gate SPILL_64bit(not); /* 098 spill 6 normal */ 15597c478bd9Sstevel@tonic-gate SPILL_mixed; /* 09C spill 7 normal */ 15607c478bd9Sstevel@tonic-gate NOT4; /* 0A0 spill 0 other */ 15617c478bd9Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUS,so1); /* 0A4 spill 1 other */ 15627c478bd9Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUS,so1); /* 0A8 spill 2 other */ 15637c478bd9Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUS,so1); /* 0AC spill 3 other */ 15647c478bd9Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUS,so1); /* 0B0 spill 4 other */ 15657c478bd9Sstevel@tonic-gate NOT4; /* 0B4 spill 5 other */ 15667c478bd9Sstevel@tonic-gate NOT4; /* 0B8 spill 6 other */ 15677c478bd9Sstevel@tonic-gate NOT4; /* 0BC spill 7 other */ 15687c478bd9Sstevel@tonic-gate NOT4; /* 0C0 fill 0 normal */ 15697c478bd9Sstevel@tonic-gate FILL_32bit_tt1(ASI_AIUP,fn1); /* 0C4 fill 1 normal */ 15707c478bd9Sstevel@tonic-gate FILL_64bit_tt1(ASI_AIUP,fn1); /* 0C8 fill 2 normal */ 15717c478bd9Sstevel@tonic-gate FILL_32bit_tt1(ASI_AIUP,fn1); /* 0CC fill 3 normal */ 15727c478bd9Sstevel@tonic-gate FILL_64bit_tt1(ASI_AIUP,fn1); /* 0D0 fill 4 normal */ 15737c478bd9Sstevel@tonic-gate FILL_32bit(not); /* 0D4 fill 5 normal */ 15747c478bd9Sstevel@tonic-gate FILL_64bit(not); /* 0D8 fill 6 normal */ 15757c478bd9Sstevel@tonic-gate FILL_mixed; /* 0DC fill 7 normal */ 15767c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 0E0 - 0EF unused */ 15777c478bd9Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 0F0 - 0FF unused */ 15787c478bd9Sstevel@tonic-gate LABELED_BAD(tt1_swtrap0); /* 100 fast ecache ECC error (cont) */ 15797c478bd9Sstevel@tonic-gate LABELED_BAD(tt1_swtrap1); /* 101 Ch+ D$ parity error (cont) */ 15807c478bd9Sstevel@tonic-gate LABELED_BAD(tt1_swtrap2); /* 102 Ch+ I$ parity error (cont) */ 15817c478bd9Sstevel@tonic-gate NOT; /* 103 reserved */ 15827c478bd9Sstevel@tonic-gate/* 15837c478bd9Sstevel@tonic-gate * We only reserve the above four special case soft traps for code running 15847c478bd9Sstevel@tonic-gate * at TL>0, so we can truncate the trap table here. 15857c478bd9Sstevel@tonic-gate */ 15867c478bd9Sstevel@tonic-gateetrap_table: 15877c478bd9Sstevel@tonic-gate .size trap_table, (.-trap_table) 15887c478bd9Sstevel@tonic-gate .size scb, (.-scb) 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate/* 15917c478bd9Sstevel@tonic-gate * We get to exec_fault in the case of an instruction miss and tte 15927c478bd9Sstevel@tonic-gate * has no execute bit set. We go to tl0 to handle it. 15937c478bd9Sstevel@tonic-gate * 15947c478bd9Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 15957c478bd9Sstevel@tonic-gate * g2 = tag access register (in) 15967c478bd9Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 15977c478bd9Sstevel@tonic-gate * g5 = tsbe data (in) 15987c478bd9Sstevel@tonic-gate * g6 = scratch (clobbered) 15997c478bd9Sstevel@tonic-gate */ 16007c478bd9Sstevel@tonic-gate ALTENTRY(exec_fault) 16017c478bd9Sstevel@tonic-gate TRACE_TSBHIT(0x200) 16027c478bd9Sstevel@tonic-gate SWITCH_GLOBALS 16037c478bd9Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g4 16047c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_IMMU, %g2 ! arg1 = addr 16057c478bd9Sstevel@tonic-gate mov T_INSTR_MMU_MISS, %g3 ! arg2 = traptype 16067c478bd9Sstevel@tonic-gate set trap, %g1 16077c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 16087c478bd9Sstevel@tonic-gate mov -1, %g4 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate.mmu_exception_not_aligned: 16117c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 16127c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g1 16137c478bd9Sstevel@tonic-gate bnz,pn %icc, 2f 16147c478bd9Sstevel@tonic-gate nop 16157c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16167c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16177c478bd9Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 16187c478bd9Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 16197c478bd9Sstevel@tonic-gate brz,pt %g5, 2f 16207c478bd9Sstevel@tonic-gate nop 16217c478bd9Sstevel@tonic-gate ldn [%g5 + P_UTRAP15], %g5 ! unaligned utrap? 16227c478bd9Sstevel@tonic-gate brz,pn %g5, 2f 16237c478bd9Sstevel@tonic-gate nop 16247c478bd9Sstevel@tonic-gate btst 1, %sp 16257c478bd9Sstevel@tonic-gate bz,pt %xcc, 1f ! 32 bit user program 16267c478bd9Sstevel@tonic-gate nop 16277c478bd9Sstevel@tonic-gate ba,pt %xcc, .setup_v9utrap ! 64 bit user program 16287c478bd9Sstevel@tonic-gate nop 16297c478bd9Sstevel@tonic-gate1: 16307c478bd9Sstevel@tonic-gate ba,pt %xcc, .setup_utrap 16317c478bd9Sstevel@tonic-gate or %g2, %g0, %g7 16327c478bd9Sstevel@tonic-gate2: 16337c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end 16347c478bd9Sstevel@tonic-gate mov T_ALIGNMENT, %g1 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate.mmu_priv_exception: 16377c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 16387c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g1 16397c478bd9Sstevel@tonic-gate bnz,pn %icc, 1f 16407c478bd9Sstevel@tonic-gate nop 16417c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16427c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16437c478bd9Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 16447c478bd9Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 16457c478bd9Sstevel@tonic-gate brz,pt %g5, 1f 16467c478bd9Sstevel@tonic-gate nop 16477c478bd9Sstevel@tonic-gate ldn [%g5 + P_UTRAP16], %g5 16487c478bd9Sstevel@tonic-gate brnz,pt %g5, .setup_v9utrap 16497c478bd9Sstevel@tonic-gate nop 16507c478bd9Sstevel@tonic-gate1: 16517c478bd9Sstevel@tonic-gate mov T_PRIV_INSTR, %g1 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate.mmu_exception_end: 16547c478bd9Sstevel@tonic-gate CPU_INDEX(%g4, %g5) 16557c478bd9Sstevel@tonic-gate set cpu_core, %g5 16567c478bd9Sstevel@tonic-gate sllx %g4, CPU_CORE_SHIFT, %g4 16577c478bd9Sstevel@tonic-gate add %g4, %g5, %g4 16587c478bd9Sstevel@tonic-gate lduh [%g4 + CPUC_DTRACE_FLAGS], %g5 16597c478bd9Sstevel@tonic-gate andcc %g5, CPU_DTRACE_NOFAULT, %g0 16607c478bd9Sstevel@tonic-gate bz %xcc, .mmu_exception_tlb_chk 16617c478bd9Sstevel@tonic-gate or %g5, CPU_DTRACE_BADADDR, %g5 16627c478bd9Sstevel@tonic-gate stuh %g5, [%g4 + CPUC_DTRACE_FLAGS] 16637c478bd9Sstevel@tonic-gate done 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate.mmu_exception_tlb_chk: 16667c478bd9Sstevel@tonic-gate GET_CPU_IMPL(%g5) ! check SFSR.FT to see if this 16677c478bd9Sstevel@tonic-gate cmp %g5, PANTHER_IMPL ! is a TLB parity error. But 16687c478bd9Sstevel@tonic-gate bne 2f ! we only do this check while 16697c478bd9Sstevel@tonic-gate mov 1, %g4 ! running on Panther CPUs 16707c478bd9Sstevel@tonic-gate sllx %g4, PN_SFSR_PARITY_SHIFT, %g4 ! since US-I/II use the same 16717c478bd9Sstevel@tonic-gate andcc %g3, %g4, %g0 ! bit for something else which 16727c478bd9Sstevel@tonic-gate bz 2f ! will be handled later. 16737c478bd9Sstevel@tonic-gate nop 16747c478bd9Sstevel@tonic-gate.mmu_exception_is_tlb_parity: 16757c478bd9Sstevel@tonic-gate .weak itlb_parity_trap 16767c478bd9Sstevel@tonic-gate .weak dtlb_parity_trap 16777c478bd9Sstevel@tonic-gate set itlb_parity_trap, %g4 16787c478bd9Sstevel@tonic-gate cmp %g1, T_INSTR_EXCEPTION ! branch to the itlb or 16797c478bd9Sstevel@tonic-gate be 3f ! dtlb parity handler 16807c478bd9Sstevel@tonic-gate nop ! if this trap is due 16817c478bd9Sstevel@tonic-gate set dtlb_parity_trap, %g4 16827c478bd9Sstevel@tonic-gate cmp %g1, T_DATA_EXCEPTION ! to a IMMU exception 16837c478bd9Sstevel@tonic-gate be 3f ! or DMMU exception. 16847c478bd9Sstevel@tonic-gate nop 16857c478bd9Sstevel@tonic-gate2: 16867c478bd9Sstevel@tonic-gate sllx %g3, 32, %g3 16877c478bd9Sstevel@tonic-gate or %g3, %g1, %g3 16887c478bd9Sstevel@tonic-gate set trap, %g1 16897c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 16907c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 16917c478bd9Sstevel@tonic-gate3: 16927c478bd9Sstevel@tonic-gate jmp %g4 ! off to the appropriate 16937c478bd9Sstevel@tonic-gate nop ! TLB parity handler 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate.fp_disabled: 16967c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16977c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16987c478bd9Sstevel@tonic-gate#ifdef SF_ERRATA_30 /* call causes fp-disabled */ 16997c478bd9Sstevel@tonic-gate brz,a,pn %g1, 2f 17007c478bd9Sstevel@tonic-gate nop 17017c478bd9Sstevel@tonic-gate#endif 17027c478bd9Sstevel@tonic-gate rdpr %tstate, %g4 17037c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g4 17047c478bd9Sstevel@tonic-gate#ifdef SF_ERRATA_30 /* call causes fp-disabled */ 17057c478bd9Sstevel@tonic-gate bnz,pn %icc, 2f 17067c478bd9Sstevel@tonic-gate nop 17077c478bd9Sstevel@tonic-gate#else 17087c478bd9Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 17097c478bd9Sstevel@tonic-gate mov PTL1_BAD_FPTRAP, %g1 17107c478bd9Sstevel@tonic-gate#endif 17117c478bd9Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 17127c478bd9Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 17137c478bd9Sstevel@tonic-gate brz,a,pt %g5, 2f 17147c478bd9Sstevel@tonic-gate nop 17157c478bd9Sstevel@tonic-gate ldn [%g5 + P_UTRAP7], %g5 ! fp_disabled utrap? 17167c478bd9Sstevel@tonic-gate brz,a,pn %g5, 2f 17177c478bd9Sstevel@tonic-gate nop 17187c478bd9Sstevel@tonic-gate btst 1, %sp 17197c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1f ! 32 bit user program 17207c478bd9Sstevel@tonic-gate nop 17217c478bd9Sstevel@tonic-gate ba,a,pt %xcc, .setup_v9utrap ! 64 bit user program 17227c478bd9Sstevel@tonic-gate nop 17237c478bd9Sstevel@tonic-gate1: 17247c478bd9Sstevel@tonic-gate ba,pt %xcc, .setup_utrap 17257c478bd9Sstevel@tonic-gate or %g0, %g0, %g7 17267c478bd9Sstevel@tonic-gate2: 17277c478bd9Sstevel@tonic-gate set fp_disabled, %g1 17287c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 17297c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate.fp_ieee_exception: 17327c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 17337c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g1 17347c478bd9Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 17357c478bd9Sstevel@tonic-gate mov PTL1_BAD_FPTRAP, %g1 17367c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 17377c478bd9Sstevel@tonic-gate stx %fsr, [%g1 + CPU_TMP1] 17387c478bd9Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %g2 17397c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 17407c478bd9Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 17417c478bd9Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 17427c478bd9Sstevel@tonic-gate brz,a,pt %g5, 1f 17437c478bd9Sstevel@tonic-gate nop 17447c478bd9Sstevel@tonic-gate ldn [%g5 + P_UTRAP8], %g5 17457c478bd9Sstevel@tonic-gate brnz,a,pt %g5, .setup_v9utrap 17467c478bd9Sstevel@tonic-gate nop 17477c478bd9Sstevel@tonic-gate1: 17487c478bd9Sstevel@tonic-gate set _fp_ieee_exception, %g1 17497c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 17507c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate/* 17537c478bd9Sstevel@tonic-gate * Register Inputs: 17547c478bd9Sstevel@tonic-gate * %g5 user trap handler 17557c478bd9Sstevel@tonic-gate * %g7 misaligned addr - for alignment traps only 17567c478bd9Sstevel@tonic-gate */ 17577c478bd9Sstevel@tonic-gate.setup_utrap: 17587c478bd9Sstevel@tonic-gate set trap, %g1 ! setup in case we go 17597c478bd9Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 ! through sys_trap on 17607c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ! the save instruction below 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate /* 17637c478bd9Sstevel@tonic-gate * If the DTrace pid provider is single stepping a copied-out 17647c478bd9Sstevel@tonic-gate * instruction, t->t_dtrace_step will be set. In that case we need 17657c478bd9Sstevel@tonic-gate * to abort the single-stepping (since execution of the instruction 17667c478bd9Sstevel@tonic-gate * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 17677c478bd9Sstevel@tonic-gate */ 17687c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME32), %sp ! window for trap handler 17697c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 17707c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 17717c478bd9Sstevel@tonic-gate ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step 17727c478bd9Sstevel@tonic-gate rdpr %tnpc, %l2 ! arg1 == tnpc 17737c478bd9Sstevel@tonic-gate brz,pt %g2, 1f 17747c478bd9Sstevel@tonic-gate rdpr %tpc, %l1 ! arg0 == tpc 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast 17777c478bd9Sstevel@tonic-gate ldn [%g1 + T_DTRACE_NPC], %l2 ! arg1 = t->t_dtrace_npc (step) 17787c478bd9Sstevel@tonic-gate brz,pt %g2, 1f 17797c478bd9Sstevel@tonic-gate st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags 17807c478bd9Sstevel@tonic-gate stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast 17817c478bd9Sstevel@tonic-gate1: 17827c478bd9Sstevel@tonic-gate mov %g7, %l3 ! arg2 == misaligned address 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 ! cwp for trap handler 17857c478bd9Sstevel@tonic-gate rdpr %cwp, %g4 17867c478bd9Sstevel@tonic-gate bclr TSTATE_CWP_MASK, %g1 17877c478bd9Sstevel@tonic-gate wrpr %g1, %g4, %tstate 17887c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %tnpc ! trap handler address 17897c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 17907c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate.check_v9utrap: 17937c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 17947c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g1 17957c478bd9Sstevel@tonic-gate bnz,a,pn %icc, 3f 17967c478bd9Sstevel@tonic-gate nop 17977c478bd9Sstevel@tonic-gate CPU_ADDR(%g4, %g1) ! load CPU struct addr 17987c478bd9Sstevel@tonic-gate ldn [%g4 + CPU_THREAD], %g5 ! load thread pointer 17997c478bd9Sstevel@tonic-gate ldn [%g5 + T_PROCP], %g5 ! load proc pointer 18007c478bd9Sstevel@tonic-gate ldn [%g5 + P_UTRAPS], %g5 ! are there utraps? 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate cmp %g3, T_SOFTWARE_TRAP 18037c478bd9Sstevel@tonic-gate bne,a,pt %icc, 1f 18047c478bd9Sstevel@tonic-gate nop 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate brz,pt %g5, 3f ! if p_utraps == NULL goto trap() 18077c478bd9Sstevel@tonic-gate rdpr %tt, %g3 ! delay - get actual hw trap type 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate sub %g3, 254, %g1 ! UT_TRAP_INSTRUCTION_16 = p_utraps[18] 18107c478bd9Sstevel@tonic-gate ba,pt %icc, 2f 18117c478bd9Sstevel@tonic-gate smul %g1, CPTRSIZE, %g2 18127c478bd9Sstevel@tonic-gate1: 18137c478bd9Sstevel@tonic-gate brz,a,pt %g5, 3f ! if p_utraps == NULL goto trap() 18147c478bd9Sstevel@tonic-gate nop 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate cmp %g3, T_UNIMP_INSTR 18177c478bd9Sstevel@tonic-gate bne,a,pt %icc, 2f 18187c478bd9Sstevel@tonic-gate nop 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate mov 1, %g1 18217c478bd9Sstevel@tonic-gate st %g1, [%g4 + CPU_TL1_HDLR] ! set CPU_TL1_HDLR 18227c478bd9Sstevel@tonic-gate rdpr %tpc, %g1 ! ld trapping instruction using 18237c478bd9Sstevel@tonic-gate lduwa [%g1]ASI_AIUP, %g1 ! "AS IF USER" ASI which could fault 18247c478bd9Sstevel@tonic-gate st %g0, [%g4 + CPU_TL1_HDLR] ! clr CPU_TL1_HDLR 18257c478bd9Sstevel@tonic-gate 18267c478bd9Sstevel@tonic-gate sethi %hi(0xc1c00000), %g4 ! setup mask for illtrap instruction 18277c478bd9Sstevel@tonic-gate andcc %g1, %g4, %g4 ! and instruction with mask 18287c478bd9Sstevel@tonic-gate bnz,a,pt %icc, 3f ! if %g4 == zero, %g1 is an ILLTRAP 18297c478bd9Sstevel@tonic-gate nop ! fall thru to setup 18307c478bd9Sstevel@tonic-gate2: 18317c478bd9Sstevel@tonic-gate ldn [%g5 + %g2], %g5 18327c478bd9Sstevel@tonic-gate brnz,a,pt %g5, .setup_v9utrap 18337c478bd9Sstevel@tonic-gate nop 18347c478bd9Sstevel@tonic-gate3: 18357c478bd9Sstevel@tonic-gate set trap, %g1 18367c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 18377c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 18387c478bd9Sstevel@tonic-gate /* NOTREACHED */ 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate/* 18417c478bd9Sstevel@tonic-gate * Register Inputs: 18427c478bd9Sstevel@tonic-gate * %g5 user trap handler 18437c478bd9Sstevel@tonic-gate */ 18447c478bd9Sstevel@tonic-gate.setup_v9utrap: 18457c478bd9Sstevel@tonic-gate set trap, %g1 ! setup in case we go 18467c478bd9Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 ! through sys_trap on 18477c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 ! the save instruction below 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate /* 18507c478bd9Sstevel@tonic-gate * If the DTrace pid provider is single stepping a copied-out 18517c478bd9Sstevel@tonic-gate * instruction, t->t_dtrace_step will be set. In that case we need 18527c478bd9Sstevel@tonic-gate * to abort the single-stepping (since execution of the instruction 18537c478bd9Sstevel@tonic-gate * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 18547c478bd9Sstevel@tonic-gate */ 18557c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME64), %sp ! window for trap handler 18567c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 18577c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 18587c478bd9Sstevel@tonic-gate ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step 18597c478bd9Sstevel@tonic-gate rdpr %tnpc, %l7 ! arg1 == tnpc 18607c478bd9Sstevel@tonic-gate brz,pt %g2, 1f 18617c478bd9Sstevel@tonic-gate rdpr %tpc, %l6 ! arg0 == tpc 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast 18647c478bd9Sstevel@tonic-gate ldn [%g1 + T_DTRACE_NPC], %l7 ! arg1 == t->t_dtrace_npc (step) 18657c478bd9Sstevel@tonic-gate brz,pt %g2, 1f 18667c478bd9Sstevel@tonic-gate st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags 18677c478bd9Sstevel@tonic-gate stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast 18687c478bd9Sstevel@tonic-gate1: 18697c478bd9Sstevel@tonic-gate rdpr %tstate, %g2 ! cwp for trap handler 18707c478bd9Sstevel@tonic-gate rdpr %cwp, %g4 18717c478bd9Sstevel@tonic-gate bclr TSTATE_CWP_MASK, %g2 18727c478bd9Sstevel@tonic-gate wrpr %g2, %g4, %tstate 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g4 ! load proc pointer 18757c478bd9Sstevel@tonic-gate ldn [%g4 + P_AS], %g4 ! load as pointer 18767c478bd9Sstevel@tonic-gate ldn [%g4 + A_USERLIMIT], %g4 ! load as userlimit 18777c478bd9Sstevel@tonic-gate cmp %l7, %g4 ! check for single-step set 18787c478bd9Sstevel@tonic-gate bne,pt %xcc, 4f 18797c478bd9Sstevel@tonic-gate nop 18807c478bd9Sstevel@tonic-gate ldn [%g1 + T_LWP], %g1 ! load klwp pointer 18817c478bd9Sstevel@tonic-gate ld [%g1 + PCB_STEP], %g4 ! load single-step flag 18827c478bd9Sstevel@tonic-gate cmp %g4, STEP_ACTIVE ! step flags set in pcb? 18837c478bd9Sstevel@tonic-gate bne,pt %icc, 4f 18847c478bd9Sstevel@tonic-gate nop 18857c478bd9Sstevel@tonic-gate stn %g5, [%g1 + PCB_TRACEPC] ! save trap handler addr in pcb 18867c478bd9Sstevel@tonic-gate mov %l7, %g4 ! on entry to precise user trap 18877c478bd9Sstevel@tonic-gate add %l6, 4, %l7 ! handler, %l6 == pc, %l7 == npc 18887c478bd9Sstevel@tonic-gate ! at time of trap 18897c478bd9Sstevel@tonic-gate wrpr %g0, %g4, %tnpc ! generate FLTBOUNDS, 18907c478bd9Sstevel@tonic-gate ! %g4 == userlimit 18917c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 18927c478bd9Sstevel@tonic-gate /* NOTREACHED */ 18937c478bd9Sstevel@tonic-gate4: 18947c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %tnpc ! trap handler address 18957c478bd9Sstevel@tonic-gate FAST_TRAP_DONE_CHK_INTR 18967c478bd9Sstevel@tonic-gate /* NOTREACHED */ 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate.fp_exception: 18997c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 19007c478bd9Sstevel@tonic-gate stx %fsr, [%g1 + CPU_TMP1] 19017c478bd9Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %g2 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate /* 19047c478bd9Sstevel@tonic-gate * Cheetah takes unfinished_FPop trap for certain range of operands 19057c478bd9Sstevel@tonic-gate * to the "fitos" instruction. Instead of going through the slow 19067c478bd9Sstevel@tonic-gate * software emulation path, we try to simulate the "fitos" instruction 19077c478bd9Sstevel@tonic-gate * via "fitod" and "fdtos" provided the following conditions are met: 19087c478bd9Sstevel@tonic-gate * 19097c478bd9Sstevel@tonic-gate * fpu_exists is set (if DEBUG) 19107c478bd9Sstevel@tonic-gate * not in privileged mode 19117c478bd9Sstevel@tonic-gate * ftt is unfinished_FPop 19127c478bd9Sstevel@tonic-gate * NXM IEEE trap is not enabled 19137c478bd9Sstevel@tonic-gate * instruction at %tpc is "fitos" 19147c478bd9Sstevel@tonic-gate * 19157c478bd9Sstevel@tonic-gate * Usage: 19167c478bd9Sstevel@tonic-gate * %g1 per cpu address 19177c478bd9Sstevel@tonic-gate * %g2 %fsr 19187c478bd9Sstevel@tonic-gate * %g6 user instruction 19197c478bd9Sstevel@tonic-gate * 19207c478bd9Sstevel@tonic-gate * Note that we can take a memory access related trap while trying 19217c478bd9Sstevel@tonic-gate * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR 19227c478bd9Sstevel@tonic-gate * flag to catch those traps and let the SFMMU code deal with page 19237c478bd9Sstevel@tonic-gate * fault and data access exception. 19247c478bd9Sstevel@tonic-gate */ 19257c478bd9Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 19267c478bd9Sstevel@tonic-gate sethi %hi(fpu_exists), %g7 19277c478bd9Sstevel@tonic-gate ld [%g7 + %lo(fpu_exists)], %g7 19287c478bd9Sstevel@tonic-gate brz,pn %g7, .fp_exception_cont 19297c478bd9Sstevel@tonic-gate nop 19307c478bd9Sstevel@tonic-gate#endif 19317c478bd9Sstevel@tonic-gate rdpr %tstate, %g7 ! branch if in privileged mode 19327c478bd9Sstevel@tonic-gate btst TSTATE_PRIV, %g7 19337c478bd9Sstevel@tonic-gate bnz,pn %xcc, .fp_exception_cont 19347c478bd9Sstevel@tonic-gate srl %g2, FSR_FTT_SHIFT, %g7 ! extract ftt from %fsr 19357c478bd9Sstevel@tonic-gate and %g7, (FSR_FTT>>FSR_FTT_SHIFT), %g7 19367c478bd9Sstevel@tonic-gate cmp %g7, FTT_UNFIN 19377c478bd9Sstevel@tonic-gate set FSR_TEM_NX, %g5 19387c478bd9Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if NOT unfinished_FPop 19397c478bd9Sstevel@tonic-gate andcc %g2, %g5, %g0 19407c478bd9Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if FSR_TEM_NX enabled 19417c478bd9Sstevel@tonic-gate rdpr %tpc, %g5 ! get faulting PC 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate or %g0, 1, %g7 19447c478bd9Sstevel@tonic-gate st %g7, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 19457c478bd9Sstevel@tonic-gate lda [%g5]ASI_USER, %g6 ! get user's instruction 19467c478bd9Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate set FITOS_INSTR_MASK, %g7 19497c478bd9Sstevel@tonic-gate and %g6, %g7, %g7 19507c478bd9Sstevel@tonic-gate set FITOS_INSTR, %g5 19517c478bd9Sstevel@tonic-gate cmp %g7, %g5 19527c478bd9Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if not FITOS_INSTR 19537c478bd9Sstevel@tonic-gate nop 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate /* 19567c478bd9Sstevel@tonic-gate * This is unfinished FPops trap for "fitos" instruction. We 19577c478bd9Sstevel@tonic-gate * need to simulate "fitos" via "fitod" and "fdtos" instruction 19587c478bd9Sstevel@tonic-gate * sequence. 19597c478bd9Sstevel@tonic-gate * 19607c478bd9Sstevel@tonic-gate * We need a temporary FP register to do the conversion. Since 19617c478bd9Sstevel@tonic-gate * both source and destination operands for the "fitos" instruction 19627c478bd9Sstevel@tonic-gate * have to be within %f0-%f31, we use an FP register from the upper 19637c478bd9Sstevel@tonic-gate * half to guarantee that it won't collide with the source or the 19647c478bd9Sstevel@tonic-gate * dest operand. However, we do have to save and restore its value. 19657c478bd9Sstevel@tonic-gate * 19667c478bd9Sstevel@tonic-gate * We use %d62 as a temporary FP register for the conversion and 19677c478bd9Sstevel@tonic-gate * branch to appropriate instruction within the conversion tables 19687c478bd9Sstevel@tonic-gate * based upon the rs2 and rd values. 19697c478bd9Sstevel@tonic-gate */ 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate std %d62, [%g1 + CPU_TMP1] ! save original value 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate srl %g6, FITOS_RS2_SHIFT, %g7 19747c478bd9Sstevel@tonic-gate and %g7, FITOS_REG_MASK, %g7 19757c478bd9Sstevel@tonic-gate set _fitos_fitod_table, %g4 19767c478bd9Sstevel@tonic-gate sllx %g7, 2, %g7 19777c478bd9Sstevel@tonic-gate jmp %g4 + %g7 19787c478bd9Sstevel@tonic-gate ba,pt %xcc, _fitos_fitod_done 19797c478bd9Sstevel@tonic-gate .empty 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate_fitos_fitod_table: 19827c478bd9Sstevel@tonic-gate fitod %f0, %d62 19837c478bd9Sstevel@tonic-gate fitod %f1, %d62 19847c478bd9Sstevel@tonic-gate fitod %f2, %d62 19857c478bd9Sstevel@tonic-gate fitod %f3, %d62 19867c478bd9Sstevel@tonic-gate fitod %f4, %d62 19877c478bd9Sstevel@tonic-gate fitod %f5, %d62 19887c478bd9Sstevel@tonic-gate fitod %f6, %d62 19897c478bd9Sstevel@tonic-gate fitod %f7, %d62 19907c478bd9Sstevel@tonic-gate fitod %f8, %d62 19917c478bd9Sstevel@tonic-gate fitod %f9, %d62 19927c478bd9Sstevel@tonic-gate fitod %f10, %d62 19937c478bd9Sstevel@tonic-gate fitod %f11, %d62 19947c478bd9Sstevel@tonic-gate fitod %f12, %d62 19957c478bd9Sstevel@tonic-gate fitod %f13, %d62 19967c478bd9Sstevel@tonic-gate fitod %f14, %d62 19977c478bd9Sstevel@tonic-gate fitod %f15, %d62 19987c478bd9Sstevel@tonic-gate fitod %f16, %d62 19997c478bd9Sstevel@tonic-gate fitod %f17, %d62 20007c478bd9Sstevel@tonic-gate fitod %f18, %d62 20017c478bd9Sstevel@tonic-gate fitod %f19, %d62 20027c478bd9Sstevel@tonic-gate fitod %f20, %d62 20037c478bd9Sstevel@tonic-gate fitod %f21, %d62 20047c478bd9Sstevel@tonic-gate fitod %f22, %d62 20057c478bd9Sstevel@tonic-gate fitod %f23, %d62 20067c478bd9Sstevel@tonic-gate fitod %f24, %d62 20077c478bd9Sstevel@tonic-gate fitod %f25, %d62 20087c478bd9Sstevel@tonic-gate fitod %f26, %d62 20097c478bd9Sstevel@tonic-gate fitod %f27, %d62 20107c478bd9Sstevel@tonic-gate fitod %f28, %d62 20117c478bd9Sstevel@tonic-gate fitod %f29, %d62 20127c478bd9Sstevel@tonic-gate fitod %f30, %d62 20137c478bd9Sstevel@tonic-gate fitod %f31, %d62 20147c478bd9Sstevel@tonic-gate_fitos_fitod_done: 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate /* 20177c478bd9Sstevel@tonic-gate * Now convert data back into single precision 20187c478bd9Sstevel@tonic-gate */ 20197c478bd9Sstevel@tonic-gate srl %g6, FITOS_RD_SHIFT, %g7 20207c478bd9Sstevel@tonic-gate and %g7, FITOS_REG_MASK, %g7 20217c478bd9Sstevel@tonic-gate set _fitos_fdtos_table, %g4 20227c478bd9Sstevel@tonic-gate sllx %g7, 2, %g7 20237c478bd9Sstevel@tonic-gate jmp %g4 + %g7 20247c478bd9Sstevel@tonic-gate ba,pt %xcc, _fitos_fdtos_done 20257c478bd9Sstevel@tonic-gate .empty 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate_fitos_fdtos_table: 20287c478bd9Sstevel@tonic-gate fdtos %d62, %f0 20297c478bd9Sstevel@tonic-gate fdtos %d62, %f1 20307c478bd9Sstevel@tonic-gate fdtos %d62, %f2 20317c478bd9Sstevel@tonic-gate fdtos %d62, %f3 20327c478bd9Sstevel@tonic-gate fdtos %d62, %f4 20337c478bd9Sstevel@tonic-gate fdtos %d62, %f5 20347c478bd9Sstevel@tonic-gate fdtos %d62, %f6 20357c478bd9Sstevel@tonic-gate fdtos %d62, %f7 20367c478bd9Sstevel@tonic-gate fdtos %d62, %f8 20377c478bd9Sstevel@tonic-gate fdtos %d62, %f9 20387c478bd9Sstevel@tonic-gate fdtos %d62, %f10 20397c478bd9Sstevel@tonic-gate fdtos %d62, %f11 20407c478bd9Sstevel@tonic-gate fdtos %d62, %f12 20417c478bd9Sstevel@tonic-gate fdtos %d62, %f13 20427c478bd9Sstevel@tonic-gate fdtos %d62, %f14 20437c478bd9Sstevel@tonic-gate fdtos %d62, %f15 20447c478bd9Sstevel@tonic-gate fdtos %d62, %f16 20457c478bd9Sstevel@tonic-gate fdtos %d62, %f17 20467c478bd9Sstevel@tonic-gate fdtos %d62, %f18 20477c478bd9Sstevel@tonic-gate fdtos %d62, %f19 20487c478bd9Sstevel@tonic-gate fdtos %d62, %f20 20497c478bd9Sstevel@tonic-gate fdtos %d62, %f21 20507c478bd9Sstevel@tonic-gate fdtos %d62, %f22 20517c478bd9Sstevel@tonic-gate fdtos %d62, %f23 20527c478bd9Sstevel@tonic-gate fdtos %d62, %f24 20537c478bd9Sstevel@tonic-gate fdtos %d62, %f25 20547c478bd9Sstevel@tonic-gate fdtos %d62, %f26 20557c478bd9Sstevel@tonic-gate fdtos %d62, %f27 20567c478bd9Sstevel@tonic-gate fdtos %d62, %f28 20577c478bd9Sstevel@tonic-gate fdtos %d62, %f29 20587c478bd9Sstevel@tonic-gate fdtos %d62, %f30 20597c478bd9Sstevel@tonic-gate fdtos %d62, %f31 20607c478bd9Sstevel@tonic-gate_fitos_fdtos_done: 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate ldd [%g1 + CPU_TMP1], %d62 ! restore %d62 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate#if DEBUG 20657c478bd9Sstevel@tonic-gate /* 20667c478bd9Sstevel@tonic-gate * Update FPop_unfinished trap kstat 20677c478bd9Sstevel@tonic-gate */ 20687c478bd9Sstevel@tonic-gate set fpustat+FPUSTAT_UNFIN_KSTAT, %g7 20697c478bd9Sstevel@tonic-gate ldx [%g7], %g5 20707c478bd9Sstevel@tonic-gate1: 20717c478bd9Sstevel@tonic-gate add %g5, 1, %g6 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate casxa [%g7] ASI_N, %g5, %g6 20747c478bd9Sstevel@tonic-gate cmp %g5, %g6 20757c478bd9Sstevel@tonic-gate bne,a,pn %xcc, 1b 20767c478bd9Sstevel@tonic-gate or %g0, %g6, %g5 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate /* 20797c478bd9Sstevel@tonic-gate * Update fpu_sim_fitos kstat 20807c478bd9Sstevel@tonic-gate */ 20817c478bd9Sstevel@tonic-gate set fpuinfo+FPUINFO_FITOS_KSTAT, %g7 20827c478bd9Sstevel@tonic-gate ldx [%g7], %g5 20837c478bd9Sstevel@tonic-gate1: 20847c478bd9Sstevel@tonic-gate add %g5, 1, %g6 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate casxa [%g7] ASI_N, %g5, %g6 20877c478bd9Sstevel@tonic-gate cmp %g5, %g6 20887c478bd9Sstevel@tonic-gate bne,a,pn %xcc, 1b 20897c478bd9Sstevel@tonic-gate or %g0, %g6, %g5 20907c478bd9Sstevel@tonic-gate#endif /* DEBUG */ 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate.fp_exception_cont: 20957c478bd9Sstevel@tonic-gate /* 20967c478bd9Sstevel@tonic-gate * Let _fp_exception deal with simulating FPop instruction. 20977c478bd9Sstevel@tonic-gate * Note that we need to pass %fsr in %g2 (already read above). 20987c478bd9Sstevel@tonic-gate */ 20997c478bd9Sstevel@tonic-gate 21007c478bd9Sstevel@tonic-gate set _fp_exception, %g1 21017c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 21027c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 21037c478bd9Sstevel@tonic-gate 210450eff769Smb158278 .global opl_cleanw_patch 210550eff769Smb158278opl_cleanw_patch: 21067c478bd9Sstevel@tonic-gate.clean_windows: 21077c478bd9Sstevel@tonic-gate set trap, %g1 21087c478bd9Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 21097c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 21107c478bd9Sstevel@tonic-gate save 21117c478bd9Sstevel@tonic-gate flushw 21127c478bd9Sstevel@tonic-gate restore 21137c478bd9Sstevel@tonic-gate wrpr %g0, %g0, %cleanwin ! no clean windows 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate CPU_ADDR(%g4, %g5) 21167c478bd9Sstevel@tonic-gate ldn [%g4 + CPU_MPCB], %g4 21177c478bd9Sstevel@tonic-gate brz,a,pn %g4, 1f 21187c478bd9Sstevel@tonic-gate nop 21197c478bd9Sstevel@tonic-gate ld [%g4 + MPCB_WSTATE], %g5 21207c478bd9Sstevel@tonic-gate add %g5, WSTATE_CLEAN_OFFSET, %g5 21217c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %wstate 21227c478bd9Sstevel@tonic-gate1: FAST_TRAP_DONE 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate/* 21257c478bd9Sstevel@tonic-gate * .spill_clean: clean the previous window, restore the wstate, and 21267c478bd9Sstevel@tonic-gate * "done". 21277c478bd9Sstevel@tonic-gate * 21287c478bd9Sstevel@tonic-gate * Entry: %g7 contains new wstate 21297c478bd9Sstevel@tonic-gate */ 21307c478bd9Sstevel@tonic-gate.spill_clean: 21317c478bd9Sstevel@tonic-gate sethi %hi(nwin_minus_one), %g5 21327c478bd9Sstevel@tonic-gate ld [%g5 + %lo(nwin_minus_one)], %g5 ! %g5 = nwin - 1 21337c478bd9Sstevel@tonic-gate rdpr %cwp, %g6 ! %g6 = %cwp 21347c478bd9Sstevel@tonic-gate deccc %g6 ! %g6-- 21357c478bd9Sstevel@tonic-gate movneg %xcc, %g5, %g6 ! if (%g6<0) %g6 = nwin-1 21367c478bd9Sstevel@tonic-gate wrpr %g6, %cwp 21377c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) 21387c478bd9Sstevel@tonic-gate clr %l0 21397c478bd9Sstevel@tonic-gate clr %l1 21407c478bd9Sstevel@tonic-gate clr %l2 21417c478bd9Sstevel@tonic-gate clr %l3 21427c478bd9Sstevel@tonic-gate clr %l4 21437c478bd9Sstevel@tonic-gate clr %l5 21447c478bd9Sstevel@tonic-gate clr %l6 21457c478bd9Sstevel@tonic-gate clr %l7 21467c478bd9Sstevel@tonic-gate wrpr %g0, %g7, %wstate 21477c478bd9Sstevel@tonic-gate saved 21487c478bd9Sstevel@tonic-gate retry ! restores correct %cwp 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate.fix_alignment: 21517c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 21527c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 21537c478bd9Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 21547c478bd9Sstevel@tonic-gate mov 1, %g2 21557c478bd9Sstevel@tonic-gate stb %g2, [%g1 + P_FIXALIGNMENT] 21567c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate#define STDF_REG(REG, ADDR, TMP) \ 21597c478bd9Sstevel@tonic-gate sll REG, 3, REG ;\ 21607c478bd9Sstevel@tonic-gatemark1: set start1, TMP ;\ 21617c478bd9Sstevel@tonic-gate jmp REG + TMP ;\ 21627c478bd9Sstevel@tonic-gate nop ;\ 21637c478bd9Sstevel@tonic-gatestart1: ba,pt %xcc, done1 ;\ 21647c478bd9Sstevel@tonic-gate std %f0, [ADDR + CPU_TMP1] ;\ 21657c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21667c478bd9Sstevel@tonic-gate std %f32, [ADDR + CPU_TMP1] ;\ 21677c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21687c478bd9Sstevel@tonic-gate std %f2, [ADDR + CPU_TMP1] ;\ 21697c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21707c478bd9Sstevel@tonic-gate std %f34, [ADDR + CPU_TMP1] ;\ 21717c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21727c478bd9Sstevel@tonic-gate std %f4, [ADDR + CPU_TMP1] ;\ 21737c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21747c478bd9Sstevel@tonic-gate std %f36, [ADDR + CPU_TMP1] ;\ 21757c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21767c478bd9Sstevel@tonic-gate std %f6, [ADDR + CPU_TMP1] ;\ 21777c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21787c478bd9Sstevel@tonic-gate std %f38, [ADDR + CPU_TMP1] ;\ 21797c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21807c478bd9Sstevel@tonic-gate std %f8, [ADDR + CPU_TMP1] ;\ 21817c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21827c478bd9Sstevel@tonic-gate std %f40, [ADDR + CPU_TMP1] ;\ 21837c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21847c478bd9Sstevel@tonic-gate std %f10, [ADDR + CPU_TMP1] ;\ 21857c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21867c478bd9Sstevel@tonic-gate std %f42, [ADDR + CPU_TMP1] ;\ 21877c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21887c478bd9Sstevel@tonic-gate std %f12, [ADDR + CPU_TMP1] ;\ 21897c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21907c478bd9Sstevel@tonic-gate std %f44, [ADDR + CPU_TMP1] ;\ 21917c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21927c478bd9Sstevel@tonic-gate std %f14, [ADDR + CPU_TMP1] ;\ 21937c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21947c478bd9Sstevel@tonic-gate std %f46, [ADDR + CPU_TMP1] ;\ 21957c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21967c478bd9Sstevel@tonic-gate std %f16, [ADDR + CPU_TMP1] ;\ 21977c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21987c478bd9Sstevel@tonic-gate std %f48, [ADDR + CPU_TMP1] ;\ 21997c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22007c478bd9Sstevel@tonic-gate std %f18, [ADDR + CPU_TMP1] ;\ 22017c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22027c478bd9Sstevel@tonic-gate std %f50, [ADDR + CPU_TMP1] ;\ 22037c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22047c478bd9Sstevel@tonic-gate std %f20, [ADDR + CPU_TMP1] ;\ 22057c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22067c478bd9Sstevel@tonic-gate std %f52, [ADDR + CPU_TMP1] ;\ 22077c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22087c478bd9Sstevel@tonic-gate std %f22, [ADDR + CPU_TMP1] ;\ 22097c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22107c478bd9Sstevel@tonic-gate std %f54, [ADDR + CPU_TMP1] ;\ 22117c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22127c478bd9Sstevel@tonic-gate std %f24, [ADDR + CPU_TMP1] ;\ 22137c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22147c478bd9Sstevel@tonic-gate std %f56, [ADDR + CPU_TMP1] ;\ 22157c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22167c478bd9Sstevel@tonic-gate std %f26, [ADDR + CPU_TMP1] ;\ 22177c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22187c478bd9Sstevel@tonic-gate std %f58, [ADDR + CPU_TMP1] ;\ 22197c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22207c478bd9Sstevel@tonic-gate std %f28, [ADDR + CPU_TMP1] ;\ 22217c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22227c478bd9Sstevel@tonic-gate std %f60, [ADDR + CPU_TMP1] ;\ 22237c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22247c478bd9Sstevel@tonic-gate std %f30, [ADDR + CPU_TMP1] ;\ 22257c478bd9Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22267c478bd9Sstevel@tonic-gate std %f62, [ADDR + CPU_TMP1] ;\ 22277c478bd9Sstevel@tonic-gatedone1: 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate#define LDDF_REG(REG, ADDR, TMP) \ 22307c478bd9Sstevel@tonic-gate sll REG, 3, REG ;\ 22317c478bd9Sstevel@tonic-gatemark2: set start2, TMP ;\ 22327c478bd9Sstevel@tonic-gate jmp REG + TMP ;\ 22337c478bd9Sstevel@tonic-gate nop ;\ 22347c478bd9Sstevel@tonic-gatestart2: ba,pt %xcc, done2 ;\ 22357c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f0 ;\ 22367c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22377c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f32 ;\ 22387c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22397c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f2 ;\ 22407c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22417c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f34 ;\ 22427c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22437c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f4 ;\ 22447c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22457c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f36 ;\ 22467c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22477c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f6 ;\ 22487c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22497c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f38 ;\ 22507c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22517c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f8 ;\ 22527c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22537c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f40 ;\ 22547c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22557c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f10 ;\ 22567c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22577c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f42 ;\ 22587c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22597c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f12 ;\ 22607c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22617c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f44 ;\ 22627c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22637c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f14 ;\ 22647c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22657c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f46 ;\ 22667c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22677c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f16 ;\ 22687c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22697c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f48 ;\ 22707c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22717c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f18 ;\ 22727c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22737c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f50 ;\ 22747c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22757c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f20 ;\ 22767c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22777c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f52 ;\ 22787c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22797c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f22 ;\ 22807c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22817c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f54 ;\ 22827c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22837c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f24 ;\ 22847c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22857c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f56 ;\ 22867c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22877c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f26 ;\ 22887c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22897c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f58 ;\ 22907c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22917c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f28 ;\ 22927c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22937c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f60 ;\ 22947c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22957c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f30 ;\ 22967c478bd9Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22977c478bd9Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f62 ;\ 22987c478bd9Sstevel@tonic-gatedone2: 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate.lddf_exception_not_aligned: 23017c478bd9Sstevel@tonic-gate /* 23027c478bd9Sstevel@tonic-gate * Cheetah overwrites SFAR on a DTLB miss, hence read it now. 23037c478bd9Sstevel@tonic-gate */ 23047c478bd9Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g5 ! misaligned vaddr in %g5 23057c478bd9Sstevel@tonic-gate 23067c478bd9Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 23077c478bd9Sstevel@tonic-gate sethi %hi(fpu_exists), %g2 ! check fpu_exists 23087c478bd9Sstevel@tonic-gate ld [%g2 + %lo(fpu_exists)], %g2 23097c478bd9Sstevel@tonic-gate brz,a,pn %g2, 4f 23107c478bd9Sstevel@tonic-gate nop 23117c478bd9Sstevel@tonic-gate#endif 23127c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23137c478bd9Sstevel@tonic-gate or %g0, 1, %g4 23147c478bd9Sstevel@tonic-gate st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate rdpr %tpc, %g2 23177c478bd9Sstevel@tonic-gate lda [%g2]ASI_AIUP, %g6 ! get the user's lddf instruction 23187c478bd9Sstevel@tonic-gate srl %g6, 23, %g1 ! using ldda or not? 23197c478bd9Sstevel@tonic-gate and %g1, 1, %g1 23207c478bd9Sstevel@tonic-gate brz,a,pt %g1, 2f ! check for ldda instruction 23217c478bd9Sstevel@tonic-gate nop 23227c478bd9Sstevel@tonic-gate srl %g6, 13, %g1 ! check immflag 23237c478bd9Sstevel@tonic-gate and %g1, 1, %g1 23247c478bd9Sstevel@tonic-gate rdpr %tstate, %g2 ! %tstate in %g2 23257c478bd9Sstevel@tonic-gate brnz,a,pn %g1, 1f 23267c478bd9Sstevel@tonic-gate srl %g2, 31, %g1 ! get asi from %tstate 23277c478bd9Sstevel@tonic-gate srl %g6, 5, %g1 ! get asi from instruction 23287c478bd9Sstevel@tonic-gate and %g1, 0xFF, %g1 ! imm_asi field 23297c478bd9Sstevel@tonic-gate1: 23307c478bd9Sstevel@tonic-gate cmp %g1, ASI_P ! primary address space 23317c478bd9Sstevel@tonic-gate be,a,pt %icc, 2f 23327c478bd9Sstevel@tonic-gate nop 23337c478bd9Sstevel@tonic-gate cmp %g1, ASI_PNF ! primary no fault address space 23347c478bd9Sstevel@tonic-gate be,a,pt %icc, 2f 23357c478bd9Sstevel@tonic-gate nop 23367c478bd9Sstevel@tonic-gate cmp %g1, ASI_S ! secondary address space 23377c478bd9Sstevel@tonic-gate be,a,pt %icc, 2f 23387c478bd9Sstevel@tonic-gate nop 23397c478bd9Sstevel@tonic-gate cmp %g1, ASI_SNF ! secondary no fault address space 23407c478bd9Sstevel@tonic-gate bne,a,pn %icc, 3f 23417c478bd9Sstevel@tonic-gate nop 23427c478bd9Sstevel@tonic-gate2: 23437c478bd9Sstevel@tonic-gate lduwa [%g5]ASI_USER, %g7 ! get first half of misaligned data 23447c478bd9Sstevel@tonic-gate add %g5, 4, %g5 ! increment misaligned data address 23457c478bd9Sstevel@tonic-gate lduwa [%g5]ASI_USER, %g5 ! get second half of misaligned data 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate sllx %g7, 32, %g7 23487c478bd9Sstevel@tonic-gate or %g5, %g7, %g5 ! combine data 23497c478bd9Sstevel@tonic-gate CPU_ADDR(%g7, %g1) ! save data on a per-cpu basis 23507c478bd9Sstevel@tonic-gate stx %g5, [%g7 + CPU_TMP1] ! save in cpu_tmp1 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate srl %g6, 25, %g3 ! %g6 has the instruction 23537c478bd9Sstevel@tonic-gate and %g3, 0x1F, %g3 ! %g3 has rd 23547c478bd9Sstevel@tonic-gate LDDF_REG(%g3, %g7, %g4) 23557c478bd9Sstevel@tonic-gate 23567c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23577c478bd9Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 23587c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 23597c478bd9Sstevel@tonic-gate3: 23607c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23617c478bd9Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 23627c478bd9Sstevel@tonic-gate4: 23637c478bd9Sstevel@tonic-gate set T_USER, %g3 ! trap type in %g3 23647c478bd9Sstevel@tonic-gate or %g3, T_LDDF_ALIGN, %g3 23657c478bd9Sstevel@tonic-gate mov %g5, %g2 ! misaligned vaddr in %g2 23667c478bd9Sstevel@tonic-gate set fpu_trap, %g1 ! goto C for the little and 23677c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap ! no fault little asi's 23687c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 23697c478bd9Sstevel@tonic-gate 23707c478bd9Sstevel@tonic-gate.stdf_exception_not_aligned: 23717c478bd9Sstevel@tonic-gate /* 23727c478bd9Sstevel@tonic-gate * Cheetah overwrites SFAR on a DTLB miss, hence read it now. 23737c478bd9Sstevel@tonic-gate */ 23747c478bd9Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g5 ! misaligned vaddr in %g5 23757c478bd9Sstevel@tonic-gate 23767c478bd9Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 23777c478bd9Sstevel@tonic-gate sethi %hi(fpu_exists), %g7 ! check fpu_exists 23787c478bd9Sstevel@tonic-gate ld [%g7 + %lo(fpu_exists)], %g3 23797c478bd9Sstevel@tonic-gate brz,a,pn %g3, 4f 23807c478bd9Sstevel@tonic-gate nop 23817c478bd9Sstevel@tonic-gate#endif 23827c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23837c478bd9Sstevel@tonic-gate or %g0, 1, %g4 23847c478bd9Sstevel@tonic-gate st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate rdpr %tpc, %g2 23877c478bd9Sstevel@tonic-gate lda [%g2]ASI_AIUP, %g6 ! get the user's stdf instruction 23887c478bd9Sstevel@tonic-gate 23897c478bd9Sstevel@tonic-gate srl %g6, 23, %g1 ! using stda or not? 23907c478bd9Sstevel@tonic-gate and %g1, 1, %g1 23917c478bd9Sstevel@tonic-gate brz,a,pt %g1, 2f ! check for stda instruction 23927c478bd9Sstevel@tonic-gate nop 23937c478bd9Sstevel@tonic-gate srl %g6, 13, %g1 ! check immflag 23947c478bd9Sstevel@tonic-gate and %g1, 1, %g1 23957c478bd9Sstevel@tonic-gate rdpr %tstate, %g2 ! %tstate in %g2 23967c478bd9Sstevel@tonic-gate brnz,a,pn %g1, 1f 23977c478bd9Sstevel@tonic-gate srl %g2, 31, %g1 ! get asi from %tstate 23987c478bd9Sstevel@tonic-gate srl %g6, 5, %g1 ! get asi from instruction 23997c478bd9Sstevel@tonic-gate and %g1, 0xFF, %g1 ! imm_asi field 24007c478bd9Sstevel@tonic-gate1: 24017c478bd9Sstevel@tonic-gate cmp %g1, ASI_P ! primary address space 24027c478bd9Sstevel@tonic-gate be,a,pt %icc, 2f 24037c478bd9Sstevel@tonic-gate nop 24047c478bd9Sstevel@tonic-gate cmp %g1, ASI_S ! secondary address space 24057c478bd9Sstevel@tonic-gate bne,a,pn %icc, 3f 24067c478bd9Sstevel@tonic-gate nop 24077c478bd9Sstevel@tonic-gate2: 24087c478bd9Sstevel@tonic-gate srl %g6, 25, %g6 24097c478bd9Sstevel@tonic-gate and %g6, 0x1F, %g6 ! %g6 has rd 24107c478bd9Sstevel@tonic-gate CPU_ADDR(%g7, %g1) 24117c478bd9Sstevel@tonic-gate STDF_REG(%g6, %g7, %g4) ! STDF_REG(REG, ADDR, TMP) 24127c478bd9Sstevel@tonic-gate 24137c478bd9Sstevel@tonic-gate ldx [%g7 + CPU_TMP1], %g6 24147c478bd9Sstevel@tonic-gate srlx %g6, 32, %g7 24157c478bd9Sstevel@tonic-gate stuwa %g7, [%g5]ASI_USER ! first half 24167c478bd9Sstevel@tonic-gate add %g5, 4, %g5 ! increment misaligned data address 24177c478bd9Sstevel@tonic-gate stuwa %g6, [%g5]ASI_USER ! second half 24187c478bd9Sstevel@tonic-gate 24197c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 24207c478bd9Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 24217c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 24227c478bd9Sstevel@tonic-gate3: 24237c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 24247c478bd9Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 24257c478bd9Sstevel@tonic-gate4: 24267c478bd9Sstevel@tonic-gate set T_USER, %g3 ! trap type in %g3 24277c478bd9Sstevel@tonic-gate or %g3, T_STDF_ALIGN, %g3 24287c478bd9Sstevel@tonic-gate mov %g5, %g2 ! misaligned vaddr in %g2 24297c478bd9Sstevel@tonic-gate set fpu_trap, %g1 ! goto C for the little and 24307c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap ! nofault little asi's 24317c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 24327c478bd9Sstevel@tonic-gate 24337c478bd9Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate.traptrace_freeze: 24367c478bd9Sstevel@tonic-gate mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4 24377c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) 24387c478bd9Sstevel@tonic-gate mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0 24397c478bd9Sstevel@tonic-gate set trap_freeze, %g1 24407c478bd9Sstevel@tonic-gate mov 1, %g2 24417c478bd9Sstevel@tonic-gate st %g2, [%g1] 24427c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 24437c478bd9Sstevel@tonic-gate 24447c478bd9Sstevel@tonic-gate.traptrace_unfreeze: 24457c478bd9Sstevel@tonic-gate set trap_freeze, %g1 24467c478bd9Sstevel@tonic-gate st %g0, [%g1] 24477c478bd9Sstevel@tonic-gate mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4 24487c478bd9Sstevel@tonic-gate TT_TRACE_L(trace_win) 24497c478bd9Sstevel@tonic-gate mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0 24507c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate#endif /* DEBUG_USER_TRAPTRACECTL */ 24537c478bd9Sstevel@tonic-gate 24547c478bd9Sstevel@tonic-gate.getcc: 24557c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 24567c478bd9Sstevel@tonic-gate stx %o0, [%g1 + CPU_TMP1] ! save %o0 24577c478bd9Sstevel@tonic-gate stx %o1, [%g1 + CPU_TMP2] ! save %o1 24587c478bd9Sstevel@tonic-gate rdpr %tstate, %g3 ! get tstate 24597c478bd9Sstevel@tonic-gate srlx %g3, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr 24607c478bd9Sstevel@tonic-gate set PSR_ICC, %g2 24617c478bd9Sstevel@tonic-gate and %o0, %g2, %o0 ! mask out the rest 24627c478bd9Sstevel@tonic-gate srl %o0, PSR_ICC_SHIFT, %o0 ! right justify 24637c478bd9Sstevel@tonic-gate rdpr %pstate, %o1 24647c478bd9Sstevel@tonic-gate wrpr %o1, PSTATE_AG, %pstate ! get into normal globals 24657c478bd9Sstevel@tonic-gate mov %o0, %g1 ! move ccr to normal %g1 24667c478bd9Sstevel@tonic-gate wrpr %g0, %o1, %pstate ! back into alternate globals 24677c478bd9Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %o0 ! restore %o0 24687c478bd9Sstevel@tonic-gate ldx [%g1 + CPU_TMP2], %o1 ! restore %o1 24697c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 24707c478bd9Sstevel@tonic-gate 24717c478bd9Sstevel@tonic-gate.setcc: 24727c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 24737c478bd9Sstevel@tonic-gate stx %o0, [%g1 + CPU_TMP1] ! save %o0 24747c478bd9Sstevel@tonic-gate stx %o1, [%g1 + CPU_TMP2] ! save %o1 24757c478bd9Sstevel@tonic-gate rdpr %pstate, %o0 24767c478bd9Sstevel@tonic-gate wrpr %o0, PSTATE_AG, %pstate ! get into normal globals 24777c478bd9Sstevel@tonic-gate mov %g1, %o1 24787c478bd9Sstevel@tonic-gate wrpr %g0, %o0, %pstate ! back to alternates 24797c478bd9Sstevel@tonic-gate sll %o1, PSR_ICC_SHIFT, %g2 24807c478bd9Sstevel@tonic-gate set PSR_ICC, %g3 24817c478bd9Sstevel@tonic-gate and %g2, %g3, %g2 ! mask out rest 24827c478bd9Sstevel@tonic-gate sllx %g2, PSR_TSTATE_CC_SHIFT, %g2 24837c478bd9Sstevel@tonic-gate rdpr %tstate, %g3 ! get tstate 24847c478bd9Sstevel@tonic-gate srl %g3, 0, %g3 ! clear upper word 24857c478bd9Sstevel@tonic-gate or %g3, %g2, %g3 ! or in new bits 24867c478bd9Sstevel@tonic-gate wrpr %g3, %tstate 24877c478bd9Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %o0 ! restore %o0 24887c478bd9Sstevel@tonic-gate ldx [%g1 + CPU_TMP2], %o1 ! restore %o1 24897c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate/* 24927c478bd9Sstevel@tonic-gate * getpsr(void) 24937c478bd9Sstevel@tonic-gate * Note that the xcc part of the ccr is not provided. 24947c478bd9Sstevel@tonic-gate * The V8 code shows why the V9 trap is not faster: 24957c478bd9Sstevel@tonic-gate * #define GETPSR_TRAP() \ 24967c478bd9Sstevel@tonic-gate * mov %psr, %i0; jmp %l2; rett %l2+4; nop; 24977c478bd9Sstevel@tonic-gate */ 24987c478bd9Sstevel@tonic-gate 24997c478bd9Sstevel@tonic-gate .type .getpsr, #function 25007c478bd9Sstevel@tonic-gate.getpsr: 25017c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 ! get tstate 25027c478bd9Sstevel@tonic-gate srlx %g1, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr 25037c478bd9Sstevel@tonic-gate set PSR_ICC, %g2 25047c478bd9Sstevel@tonic-gate and %o0, %g2, %o0 ! mask out the rest 25057c478bd9Sstevel@tonic-gate 25067c478bd9Sstevel@tonic-gate rd %fprs, %g1 ! get fprs 25077c478bd9Sstevel@tonic-gate and %g1, FPRS_FEF, %g2 ! mask out dirty upper/lower 25087c478bd9Sstevel@tonic-gate sllx %g2, PSR_FPRS_FEF_SHIFT, %g2 ! shift fef to V8 psr.ef 25097c478bd9Sstevel@tonic-gate or %o0, %g2, %o0 ! or result into psr.ef 25107c478bd9Sstevel@tonic-gate 25117c478bd9Sstevel@tonic-gate set V9_PSR_IMPLVER, %g2 ! SI assigned impl/ver: 0xef 25127c478bd9Sstevel@tonic-gate or %o0, %g2, %o0 ! or psr.impl/ver 25137c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 25147c478bd9Sstevel@tonic-gate SET_SIZE(.getpsr) 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate/* 25177c478bd9Sstevel@tonic-gate * setpsr(newpsr) 25187c478bd9Sstevel@tonic-gate * Note that there is no support for ccr.xcc in the V9 code. 25197c478bd9Sstevel@tonic-gate */ 25207c478bd9Sstevel@tonic-gate 25217c478bd9Sstevel@tonic-gate .type .setpsr, #function 25227c478bd9Sstevel@tonic-gate.setpsr: 25237c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 ! get tstate 25247c478bd9Sstevel@tonic-gate! setx TSTATE_V8_UBITS, %g2 25257c478bd9Sstevel@tonic-gate or %g0, CCR_ICC, %g3 25267c478bd9Sstevel@tonic-gate sllx %g3, TSTATE_CCR_SHIFT, %g2 25277c478bd9Sstevel@tonic-gate 25287c478bd9Sstevel@tonic-gate andn %g1, %g2, %g1 ! zero current user bits 25297c478bd9Sstevel@tonic-gate set PSR_ICC, %g2 25307c478bd9Sstevel@tonic-gate and %g2, %o0, %g2 ! clear all but psr.icc bits 25317c478bd9Sstevel@tonic-gate sllx %g2, PSR_TSTATE_CC_SHIFT, %g3 ! shift to tstate.ccr.icc 25327c478bd9Sstevel@tonic-gate wrpr %g1, %g3, %tstate ! write tstate 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate set PSR_EF, %g2 25357c478bd9Sstevel@tonic-gate and %g2, %o0, %g2 ! clear all but fp enable bit 25367c478bd9Sstevel@tonic-gate srlx %g2, PSR_FPRS_FEF_SHIFT, %g4 ! shift ef to V9 fprs.fef 25377c478bd9Sstevel@tonic-gate wr %g0, %g4, %fprs ! write fprs 25387c478bd9Sstevel@tonic-gate 25397c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 25407c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 25417c478bd9Sstevel@tonic-gate ldn [%g2 + T_LWP], %g3 ! load klwp pointer 25427c478bd9Sstevel@tonic-gate ldn [%g3 + LWP_FPU], %g2 ! get lwp_fpu pointer 25437c478bd9Sstevel@tonic-gate stuw %g4, [%g2 + FPU_FPRS] ! write fef value to fpu_fprs 25447c478bd9Sstevel@tonic-gate srlx %g4, 2, %g4 ! shift fef value to bit 0 25457c478bd9Sstevel@tonic-gate stub %g4, [%g2 + FPU_EN] ! write fef value to fpu_en 25467c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 25477c478bd9Sstevel@tonic-gate SET_SIZE(.setpsr) 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate/* 25507c478bd9Sstevel@tonic-gate * getlgrp 25517c478bd9Sstevel@tonic-gate * get home lgrpid on which the calling thread is currently executing. 25527c478bd9Sstevel@tonic-gate */ 25537c478bd9Sstevel@tonic-gate .type .getlgrp, #function 25547c478bd9Sstevel@tonic-gate.getlgrp: 25557c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 25567c478bd9Sstevel@tonic-gate ld [%g1 + CPU_ID], %o0 ! load cpu_id 25577c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 25587c478bd9Sstevel@tonic-gate ldn [%g2 + T_LPL], %g2 ! load lpl pointer 25597c478bd9Sstevel@tonic-gate ld [%g2 + LPL_LGRPID], %g1 ! load lpl_lgrpid 25607c478bd9Sstevel@tonic-gate sra %g1, 0, %o1 25617c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 25627c478bd9Sstevel@tonic-gate SET_SIZE(.getlgrp) 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate/* 25657c478bd9Sstevel@tonic-gate * Entry for old 4.x trap (trap 0). 25667c478bd9Sstevel@tonic-gate */ 25677c478bd9Sstevel@tonic-gate ENTRY_NP(syscall_trap_4x) 25687c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 25697c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 25707c478bd9Sstevel@tonic-gate ldn [%g2 + T_LWP], %g2 ! load klwp pointer 25717c478bd9Sstevel@tonic-gate ld [%g2 + PCB_TRAP0], %g2 ! lwp->lwp_pcb.pcb_trap0addr 25727c478bd9Sstevel@tonic-gate brz,pn %g2, 1f ! has it been set? 25737c478bd9Sstevel@tonic-gate st %l0, [%g1 + CPU_TMP1] ! delay - save some locals 25747c478bd9Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 25757c478bd9Sstevel@tonic-gate rdpr %tnpc, %l1 ! save old tnpc 25767c478bd9Sstevel@tonic-gate wrpr %g0, %g2, %tnpc ! setup tnpc 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate rdpr %pstate, %l0 25797c478bd9Sstevel@tonic-gate wrpr %l0, PSTATE_AG, %pstate ! switch to normal globals 25807c478bd9Sstevel@tonic-gate mov %l1, %g6 ! pass tnpc to user code in %g6 25817c478bd9Sstevel@tonic-gate wrpr %l0, %g0, %pstate ! switch back to alternate globals 25827c478bd9Sstevel@tonic-gate 25837c478bd9Sstevel@tonic-gate ! Note that %g1 still contains CPU struct addr 25847c478bd9Sstevel@tonic-gate ld [%g1 + CPU_TMP2], %l1 ! restore locals 25857c478bd9Sstevel@tonic-gate ld [%g1 + CPU_TMP1], %l0 25867c478bd9Sstevel@tonic-gate FAST_TRAP_DONE_CHK_INTR 25877c478bd9Sstevel@tonic-gate1: 25887c478bd9Sstevel@tonic-gate mov %g1, %l0 25897c478bd9Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 25907c478bd9Sstevel@tonic-gate rdpr %pstate, %l1 25917c478bd9Sstevel@tonic-gate wrpr %l1, PSTATE_AG, %pstate 25927c478bd9Sstevel@tonic-gate ! 25937c478bd9Sstevel@tonic-gate ! check for old syscall mmap which is the only different one which 25947c478bd9Sstevel@tonic-gate ! must be the same. Others are handled in the compatibility library. 25957c478bd9Sstevel@tonic-gate ! 25967c478bd9Sstevel@tonic-gate cmp %g1, OSYS_mmap ! compare to old 4.x mmap 25977c478bd9Sstevel@tonic-gate movz %icc, SYS_mmap, %g1 25987c478bd9Sstevel@tonic-gate wrpr %g0, %l1, %pstate 25997c478bd9Sstevel@tonic-gate ld [%l0 + CPU_TMP2], %l1 ! restore locals 26007c478bd9Sstevel@tonic-gate ld [%l0 + CPU_TMP1], %l0 26017c478bd9Sstevel@tonic-gate SYSCALL(syscall_trap32) 26027c478bd9Sstevel@tonic-gate SET_SIZE(syscall_trap_4x) 26037c478bd9Sstevel@tonic-gate 26047c478bd9Sstevel@tonic-gate/* 26057c478bd9Sstevel@tonic-gate * Handler for software trap 9. 26067c478bd9Sstevel@tonic-gate * Set trap0 emulation address for old 4.x system call trap. 26077c478bd9Sstevel@tonic-gate * XXX - this should be a system call. 26087c478bd9Sstevel@tonic-gate */ 26097c478bd9Sstevel@tonic-gate ENTRY_NP(set_trap0_addr) 26107c478bd9Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 26117c478bd9Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 26127c478bd9Sstevel@tonic-gate ldn [%g2 + T_LWP], %g2 ! load klwp pointer 26137c478bd9Sstevel@tonic-gate st %l0, [%g1 + CPU_TMP1] ! save some locals 26147c478bd9Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 26157c478bd9Sstevel@tonic-gate rdpr %pstate, %l0 26167c478bd9Sstevel@tonic-gate wrpr %l0, PSTATE_AG, %pstate 26177c478bd9Sstevel@tonic-gate mov %g1, %l1 26187c478bd9Sstevel@tonic-gate wrpr %g0, %l0, %pstate 26197c478bd9Sstevel@tonic-gate andn %l1, 3, %l1 ! force alignment 26207c478bd9Sstevel@tonic-gate st %l1, [%g2 + PCB_TRAP0] ! lwp->lwp_pcb.pcb_trap0addr 26217c478bd9Sstevel@tonic-gate ld [%g1 + CPU_TMP1], %l0 ! restore locals 26227c478bd9Sstevel@tonic-gate ld [%g1 + CPU_TMP2], %l1 26237c478bd9Sstevel@tonic-gate FAST_TRAP_DONE 26247c478bd9Sstevel@tonic-gate SET_SIZE(set_trap0_addr) 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate/* 26277c478bd9Sstevel@tonic-gate * mmu_trap_tl1 26287c478bd9Sstevel@tonic-gate * trap handler for unexpected mmu traps. 26297c478bd9Sstevel@tonic-gate * simply checks if the trap was a user lddf/stdf alignment trap, in which 26307c478bd9Sstevel@tonic-gate * case we go to fpu_trap or a user trap from the window handler, in which 26317c478bd9Sstevel@tonic-gate * case we go save the state on the pcb. Otherwise, we go to ptl1_panic. 26327c478bd9Sstevel@tonic-gate */ 26337c478bd9Sstevel@tonic-gate .type mmu_trap_tl1, #function 26347c478bd9Sstevel@tonic-gatemmu_trap_tl1: 26357c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 26367c478bd9Sstevel@tonic-gate TRACE_PTR(%g5, %g6) 2637*023e71deSHaik Aftandilian GET_TRACE_TICK(%g6, %g7) 26387c478bd9Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_TICK]%asi 26397c478bd9Sstevel@tonic-gate rdpr %tl, %g6 26407c478bd9Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TL]%asi 26417c478bd9Sstevel@tonic-gate rdpr %tt, %g6 26427c478bd9Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TT]%asi 26437c478bd9Sstevel@tonic-gate rdpr %tstate, %g6 26447c478bd9Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi 26457c478bd9Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 26467c478bd9Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 26477c478bd9Sstevel@tonic-gate rdpr %tpc, %g6 26487c478bd9Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_TPC]%asi 26497c478bd9Sstevel@tonic-gate set MMU_SFAR, %g6 26507c478bd9Sstevel@tonic-gate ldxa [%g6]ASI_DMMU, %g6 26517c478bd9Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_F1]%asi 26527c478bd9Sstevel@tonic-gate CPU_PADDR(%g7, %g6); 26537c478bd9Sstevel@tonic-gate add %g7, CPU_TL1_HDLR, %g7 26547c478bd9Sstevel@tonic-gate lda [%g7]ASI_MEM, %g6 26557c478bd9Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_F2]%asi 26567c478bd9Sstevel@tonic-gate set 0xdeadbeef, %g6 26577c478bd9Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F3]%asi 26587c478bd9Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F4]%asi 26597c478bd9Sstevel@tonic-gate TRACE_NEXT(%g5, %g6, %g7) 26607c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */ 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate GET_CPU_IMPL(%g5) 26637c478bd9Sstevel@tonic-gate cmp %g5, PANTHER_IMPL 26647c478bd9Sstevel@tonic-gate bne mmu_trap_tl1_4 26657c478bd9Sstevel@tonic-gate nop 26667c478bd9Sstevel@tonic-gate rdpr %tt, %g5 26677c478bd9Sstevel@tonic-gate cmp %g5, T_DATA_EXCEPTION 26687c478bd9Sstevel@tonic-gate bne mmu_trap_tl1_4 26697c478bd9Sstevel@tonic-gate nop 26707c478bd9Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi 26717c478bd9Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g5 26727c478bd9Sstevel@tonic-gate mov 1, %g6 26737c478bd9Sstevel@tonic-gate sllx %g6, PN_SFSR_PARITY_SHIFT, %g6 26747c478bd9Sstevel@tonic-gate andcc %g5, %g6, %g0 26757c478bd9Sstevel@tonic-gate bz mmu_trap_tl1_4 26767c478bd9Sstevel@tonic-gate 26777c478bd9Sstevel@tonic-gate /* 26787c478bd9Sstevel@tonic-gate * We are running on a Panther and have hit a DTLB parity error. 26797c478bd9Sstevel@tonic-gate */ 26807c478bd9Sstevel@tonic-gate ldxa [MMU_TAG_ACCESS]%asi, %g2 26817c478bd9Sstevel@tonic-gate mov %g5, %g3 26827c478bd9Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_is_tlb_parity 26837c478bd9Sstevel@tonic-gate mov T_DATA_EXCEPTION, %g1 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gatemmu_trap_tl1_4: 26867c478bd9Sstevel@tonic-gate CPU_PADDR(%g7, %g6); 26877c478bd9Sstevel@tonic-gate add %g7, CPU_TL1_HDLR, %g7 ! %g7 = &cpu_m.tl1_hdlr (PA) 26887c478bd9Sstevel@tonic-gate /* 26897c478bd9Sstevel@tonic-gate * AM is cleared on trap, so addresses are 64 bit 26907c478bd9Sstevel@tonic-gate */ 26917c478bd9Sstevel@tonic-gate lda [%g7]ASI_MEM, %g6 26927c478bd9Sstevel@tonic-gate brz,a,pt %g6, 1f 26937c478bd9Sstevel@tonic-gate nop 26947c478bd9Sstevel@tonic-gate /* 26957c478bd9Sstevel@tonic-gate * We are going to update cpu_m.tl1_hdlr using physical address. 26967c478bd9Sstevel@tonic-gate * Flush the D$ line, so that stale data won't be accessed later. 26977c478bd9Sstevel@tonic-gate */ 26987c478bd9Sstevel@tonic-gate CPU_ADDR(%g6, %g5) 26997c478bd9Sstevel@tonic-gate add %g6, CPU_TL1_HDLR, %g6 ! %g6 = &cpu_m.tl1_hdlr (VA) 27007c478bd9Sstevel@tonic-gate GET_CPU_IMPL(%g5) 27017c478bd9Sstevel@tonic-gate cmp %g5, CHEETAH_IMPL 270225cf1a30Sjl139090 bl,pt %icc, 3f 270325cf1a30Sjl139090 cmp %g5, SPITFIRE_IMPL 27047c478bd9Sstevel@tonic-gate stxa %g0, [%g7]ASI_DC_INVAL 27057c478bd9Sstevel@tonic-gate membar #Sync 27067c478bd9Sstevel@tonic-gate ba,pt %xcc, 2f 27077c478bd9Sstevel@tonic-gate nop 27087c478bd9Sstevel@tonic-gate3: 270925cf1a30Sjl139090 bl,pt %icc, 2f 271025cf1a30Sjl139090 sethi %hi(dcache_line_mask), %g5 27117c478bd9Sstevel@tonic-gate ld [%g5 + %lo(dcache_line_mask)], %g5 27127c478bd9Sstevel@tonic-gate and %g6, %g5, %g5 27137c478bd9Sstevel@tonic-gate stxa %g0, [%g5]ASI_DC_TAG 27147c478bd9Sstevel@tonic-gate membar #Sync 27157c478bd9Sstevel@tonic-gate2: 27167c478bd9Sstevel@tonic-gate sta %g0, [%g7]ASI_MEM 27177c478bd9Sstevel@tonic-gate SWITCH_GLOBALS ! back to mmu globals 27187c478bd9Sstevel@tonic-gate ba,a,pt %xcc, sfmmu_mmu_trap ! handle page faults 27197c478bd9Sstevel@tonic-gate1: 27207c478bd9Sstevel@tonic-gate rdpr %tt, %g5 27217c478bd9Sstevel@tonic-gate rdpr %tl, %g7 27227c478bd9Sstevel@tonic-gate sub %g7, 1, %g6 27237c478bd9Sstevel@tonic-gate wrpr %g6, %tl 27247c478bd9Sstevel@tonic-gate rdpr %tt, %g6 27257c478bd9Sstevel@tonic-gate wrpr %g7, %tl 27267c478bd9Sstevel@tonic-gate and %g6, WTRAP_TTMASK, %g6 27277c478bd9Sstevel@tonic-gate cmp %g6, WTRAP_TYPE 27287c478bd9Sstevel@tonic-gate bne,a,pn %xcc, ptl1_panic 27297c478bd9Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 27307c478bd9Sstevel@tonic-gate rdpr %tpc, %g7 27317c478bd9Sstevel@tonic-gate /* tpc should be in the trap table */ 27327c478bd9Sstevel@tonic-gate set trap_table, %g6 27337c478bd9Sstevel@tonic-gate cmp %g7, %g6 27347c478bd9Sstevel@tonic-gate blt,a,pn %xcc, ptl1_panic 27357c478bd9Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 27367c478bd9Sstevel@tonic-gate set etrap_table, %g6 27377c478bd9Sstevel@tonic-gate cmp %g7, %g6 27387c478bd9Sstevel@tonic-gate bge,a,pn %xcc, ptl1_panic 27397c478bd9Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 27407c478bd9Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 27417c478bd9Sstevel@tonic-gate move %icc, MMU_SFAR, %g6 27427c478bd9Sstevel@tonic-gate movne %icc, MMU_TAG_ACCESS, %g6 27437c478bd9Sstevel@tonic-gate ldxa [%g6]ASI_DMMU, %g6 27447c478bd9Sstevel@tonic-gate andn %g7, WTRAP_ALIGN, %g7 /* 128 byte aligned */ 27457c478bd9Sstevel@tonic-gate add %g7, WTRAP_FAULTOFF, %g7 27467c478bd9Sstevel@tonic-gate wrpr %g0, %g7, %tnpc 27477c478bd9Sstevel@tonic-gate done 27487c478bd9Sstevel@tonic-gate SET_SIZE(mmu_trap_tl1) 27497c478bd9Sstevel@tonic-gate 27507c478bd9Sstevel@tonic-gate/* 27517c478bd9Sstevel@tonic-gate * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers. These 27527c478bd9Sstevel@tonic-gate * traps are valid only when kmdb is loaded. When the debugger is active, 27537c478bd9Sstevel@tonic-gate * the code below is rewritten to transfer control to the appropriate 27547c478bd9Sstevel@tonic-gate * debugger entry points. 27557c478bd9Sstevel@tonic-gate */ 27567c478bd9Sstevel@tonic-gate .global kmdb_trap 27577c478bd9Sstevel@tonic-gate .align 8 27587c478bd9Sstevel@tonic-gatekmdb_trap: 27597c478bd9Sstevel@tonic-gate ba,a trap_table0 27607c478bd9Sstevel@tonic-gate jmp %g1 + 0 27617c478bd9Sstevel@tonic-gate nop 27627c478bd9Sstevel@tonic-gate 27637c478bd9Sstevel@tonic-gate .global kmdb_trap_tl1 27647c478bd9Sstevel@tonic-gate .align 8 27657c478bd9Sstevel@tonic-gatekmdb_trap_tl1: 27667c478bd9Sstevel@tonic-gate ba,a trap_table0 27677c478bd9Sstevel@tonic-gate jmp %g1 + 0 27687c478bd9Sstevel@tonic-gate nop 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate/* 27717c478bd9Sstevel@tonic-gate * This entry is copied from OBP's trap table during boot. 27727c478bd9Sstevel@tonic-gate */ 27737c478bd9Sstevel@tonic-gate .global obp_bpt 27747c478bd9Sstevel@tonic-gate .align 8 27757c478bd9Sstevel@tonic-gateobp_bpt: 27767c478bd9Sstevel@tonic-gate NOT 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate/* 27797c478bd9Sstevel@tonic-gate * if kernel, set PCONTEXT to 0 for debuggers 27807c478bd9Sstevel@tonic-gate * if user, clear nucleus page sizes 27817c478bd9Sstevel@tonic-gate */ 27827c478bd9Sstevel@tonic-gate .global kctx_obp_bpt 27837c478bd9Sstevel@tonic-gatekctx_obp_bpt: 27847c478bd9Sstevel@tonic-gate set obp_bpt, %g2 27857c478bd9Sstevel@tonic-gate1: 2786febcc4a5Sjimand#ifndef _OPL 27877c478bd9Sstevel@tonic-gate mov MMU_PCONTEXT, %g1 27887c478bd9Sstevel@tonic-gate ldxa [%g1]ASI_DMMU, %g1 27897c478bd9Sstevel@tonic-gate srlx %g1, CTXREG_NEXT_SHIFT, %g3 27907c478bd9Sstevel@tonic-gate brz,pt %g3, 3f ! nucleus pgsz is 0, no problem 27917c478bd9Sstevel@tonic-gate sllx %g3, CTXREG_NEXT_SHIFT, %g3 27927c478bd9Sstevel@tonic-gate set CTXREG_CTX_MASK, %g4 ! check Pcontext 27937c478bd9Sstevel@tonic-gate btst %g4, %g1 27947c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 2f 27957c478bd9Sstevel@tonic-gate clr %g3 ! kernel: PCONTEXT=0 27967c478bd9Sstevel@tonic-gate xor %g3, %g1, %g3 ! user: clr N_pgsz0/1 bits 27977c478bd9Sstevel@tonic-gate2: 27987c478bd9Sstevel@tonic-gate set DEMAP_ALL_TYPE, %g1 27997c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 28007c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 28017c478bd9Sstevel@tonic-gate mov MMU_PCONTEXT, %g1 28027c478bd9Sstevel@tonic-gate stxa %g3, [%g1]ASI_DMMU 28037c478bd9Sstevel@tonic-gate membar #Sync 28047c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g1 28057c478bd9Sstevel@tonic-gate flush %g1 ! flush required by immu 2806febcc4a5Sjimand#endif /* _OPL */ 28077c478bd9Sstevel@tonic-gate3: 28087c478bd9Sstevel@tonic-gate jmp %g2 28097c478bd9Sstevel@tonic-gate nop 28107c478bd9Sstevel@tonic-gate 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 28137c478bd9Sstevel@tonic-gate/* 28147c478bd9Sstevel@tonic-gate * TRAPTRACE support. 28157c478bd9Sstevel@tonic-gate * labels here are branched to with "rd %pc, %g7" in the delay slot. 28167c478bd9Sstevel@tonic-gate * Return is done by "jmp %g7 + 4". 28177c478bd9Sstevel@tonic-gate */ 28187c478bd9Sstevel@tonic-gate 28197c478bd9Sstevel@tonic-gatetrace_gen: 28207c478bd9Sstevel@tonic-gate TRACE_PTR(%g3, %g6) 2821*023e71deSHaik Aftandilian GET_TRACE_TICK(%g6, %g4) 28227c478bd9Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 28237c478bd9Sstevel@tonic-gate rdpr %tl, %g6 28247c478bd9Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TL]%asi 28257c478bd9Sstevel@tonic-gate rdpr %tt, %g6 28267c478bd9Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi 28277c478bd9Sstevel@tonic-gate rdpr %tstate, %g6 28287c478bd9Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TSTATE]%asi 28297c478bd9Sstevel@tonic-gate stna %sp, [%g3 + TRAP_ENT_SP]%asi 28307c478bd9Sstevel@tonic-gate rdpr %tpc, %g6 28317c478bd9Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_TPC]%asi 28327c478bd9Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g5) 28337c478bd9Sstevel@tonic-gate jmp %g7 + 4 28347c478bd9Sstevel@tonic-gate nop 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gatetrace_win: 28377c478bd9Sstevel@tonic-gate TRACE_WIN_INFO(0, %l0, %l1, %l2) 28387c478bd9Sstevel@tonic-gate ! Keep the locals as clean as possible, caller cleans %l4 28397c478bd9Sstevel@tonic-gate clr %l2 28407c478bd9Sstevel@tonic-gate clr %l1 28417c478bd9Sstevel@tonic-gate jmp %l4 + 4 28427c478bd9Sstevel@tonic-gate clr %l0 28437c478bd9Sstevel@tonic-gate 28447c478bd9Sstevel@tonic-gate/* 28457c478bd9Sstevel@tonic-gate * Trace a tsb hit 28467c478bd9Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 28477c478bd9Sstevel@tonic-gate * g2 = tag access register (in) 28487c478bd9Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 28497c478bd9Sstevel@tonic-gate * g5 = tsbe data (in) 28507c478bd9Sstevel@tonic-gate * g6 = scratch (clobbered) 28517c478bd9Sstevel@tonic-gate * g7 = pc we jumped here from (in) 28527c478bd9Sstevel@tonic-gate */ 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate ! Do not disturb %g5, it will be used after the trace 28557c478bd9Sstevel@tonic-gate ALTENTRY(trace_tsbhit) 28567c478bd9Sstevel@tonic-gate TRACE_TSBHIT(0) 28577c478bd9Sstevel@tonic-gate jmp %g7 + 4 28587c478bd9Sstevel@tonic-gate nop 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate/* 28617c478bd9Sstevel@tonic-gate * Trace a TSB miss 28627c478bd9Sstevel@tonic-gate * 28637c478bd9Sstevel@tonic-gate * g1 = tsb8k pointer (in) 28647c478bd9Sstevel@tonic-gate * g2 = tag access register (in) 28657c478bd9Sstevel@tonic-gate * g3 = tsb4m pointer (in) 28667c478bd9Sstevel@tonic-gate * g4 = tsbe tag (in/clobbered) 28677c478bd9Sstevel@tonic-gate * g5 - g6 = scratch (clobbered) 28687c478bd9Sstevel@tonic-gate * g7 = pc we jumped here from (in) 28697c478bd9Sstevel@tonic-gate */ 28707c478bd9Sstevel@tonic-gate .global trace_tsbmiss 28717c478bd9Sstevel@tonic-gatetrace_tsbmiss: 28727c478bd9Sstevel@tonic-gate membar #Sync 28737c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 28747c478bd9Sstevel@tonic-gate flush %g6 28757c478bd9Sstevel@tonic-gate TRACE_PTR(%g5, %g6) 28767c478bd9Sstevel@tonic-gate stxa %g2, [%g5 + TRAP_ENT_SP]%asi ! tag access 28777c478bd9Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_F1]%asi ! tsb tag 2878*023e71deSHaik Aftandilian GET_TRACE_TICK(%g6, %g4) 2879*023e71deSHaik Aftandilian stxa %g6, [%g5 + TRAP_ENT_TICK]%asi 28807c478bd9Sstevel@tonic-gate rdpr %tnpc, %g6 28817c478bd9Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_F2]%asi 28827c478bd9Sstevel@tonic-gate stna %g1, [%g5 + TRAP_ENT_F3]%asi ! tsb8k pointer 28837c478bd9Sstevel@tonic-gate srlx %g1, 32, %g6 28847c478bd9Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F4]%asi ! huh? 28857c478bd9Sstevel@tonic-gate rdpr %tpc, %g6 28867c478bd9Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_TPC]%asi 28877c478bd9Sstevel@tonic-gate rdpr %tl, %g6 28887c478bd9Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TL]%asi 28897c478bd9Sstevel@tonic-gate rdpr %tt, %g6 28907c478bd9Sstevel@tonic-gate or %g6, TT_MMU_MISS, %g4 28917c478bd9Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 28927c478bd9Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT 28937c478bd9Sstevel@tonic-gate be,a %icc, 1f 28947c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_IMMU, %g6 28957c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DMMU, %g6 28967c478bd9Sstevel@tonic-gate1: stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! tag target 28977c478bd9Sstevel@tonic-gate stxa %g3, [%g5 + TRAP_ENT_TR]%asi ! tsb4m pointer 28987c478bd9Sstevel@tonic-gate TRACE_NEXT(%g5, %g4, %g6) 28997c478bd9Sstevel@tonic-gate jmp %g7 + 4 29007c478bd9Sstevel@tonic-gate nop 29017c478bd9Sstevel@tonic-gate 29027c478bd9Sstevel@tonic-gate/* 29037c478bd9Sstevel@tonic-gate * g2 = tag access register (in) 29047c478bd9Sstevel@tonic-gate * g3 = ctx number (in) 29057c478bd9Sstevel@tonic-gate */ 29067c478bd9Sstevel@tonic-gatetrace_dataprot: 29077c478bd9Sstevel@tonic-gate membar #Sync 29087c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 29097c478bd9Sstevel@tonic-gate flush %g6 29107c478bd9Sstevel@tonic-gate TRACE_PTR(%g1, %g6) 2911*023e71deSHaik Aftandilian GET_TRACE_TICK(%g6, %g5) 29127c478bd9Sstevel@tonic-gate stxa %g6, [%g1 + TRAP_ENT_TICK]%asi 29137c478bd9Sstevel@tonic-gate rdpr %tpc, %g6 29147c478bd9Sstevel@tonic-gate stna %g6, [%g1 + TRAP_ENT_TPC]%asi 29157c478bd9Sstevel@tonic-gate rdpr %tstate, %g6 29167c478bd9Sstevel@tonic-gate stxa %g6, [%g1 + TRAP_ENT_TSTATE]%asi 29177c478bd9Sstevel@tonic-gate stxa %g2, [%g1 + TRAP_ENT_SP]%asi ! tag access reg 29187c478bd9Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_TR]%asi 29197c478bd9Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F1]%asi 29207c478bd9Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F2]%asi 29217c478bd9Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F3]%asi 29227c478bd9Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F4]%asi 29237c478bd9Sstevel@tonic-gate rdpr %tl, %g6 29247c478bd9Sstevel@tonic-gate stha %g6, [%g1 + TRAP_ENT_TL]%asi 29257c478bd9Sstevel@tonic-gate rdpr %tt, %g6 29267c478bd9Sstevel@tonic-gate stha %g6, [%g1 + TRAP_ENT_TT]%asi 29277c478bd9Sstevel@tonic-gate TRACE_NEXT(%g1, %g4, %g5) 29287c478bd9Sstevel@tonic-gate jmp %g7 + 4 29297c478bd9Sstevel@tonic-gate nop 29307c478bd9Sstevel@tonic-gate 29317c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */ 29327c478bd9Sstevel@tonic-gate 2933b9e93c10SJonathan Haslam .align 32 2934b9e93c10SJonathan Haslam .global pil15_epilogue 2935b9e93c10SJonathan Haslampil15_epilogue: 2936b9e93c10SJonathan Haslam ba pil_interrupt_common 2937b9e93c10SJonathan Haslam nop 2938b9e93c10SJonathan Haslam .align 32 2939b9e93c10SJonathan Haslam 29407c478bd9Sstevel@tonic-gate/* 29417c478bd9Sstevel@tonic-gate * fast_trap_done, fast_trap_done_chk_intr: 29427c478bd9Sstevel@tonic-gate * 29437c478bd9Sstevel@tonic-gate * Due to the design of UltraSPARC pipeline, pending interrupts are not 29447c478bd9Sstevel@tonic-gate * taken immediately after a RETRY or DONE instruction which causes IE to 29457c478bd9Sstevel@tonic-gate * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed 29467c478bd9Sstevel@tonic-gate * to execute first before taking any interrupts. If that instruction 29477c478bd9Sstevel@tonic-gate * results in other traps, and if the corresponding trap handler runs 29487c478bd9Sstevel@tonic-gate * entirely at TL=1 with interrupts disabled, then pending interrupts 29497c478bd9Sstevel@tonic-gate * won't be taken until after yet another instruction following the %tpc 29507c478bd9Sstevel@tonic-gate * or %tnpc. 29517c478bd9Sstevel@tonic-gate * 29527c478bd9Sstevel@tonic-gate * A malicious user program can use this feature to block out interrupts 29537c478bd9Sstevel@tonic-gate * for extended durations, which can result in send_mondo_timeout kernel 29547c478bd9Sstevel@tonic-gate * panic. 29557c478bd9Sstevel@tonic-gate * 29567c478bd9Sstevel@tonic-gate * This problem is addressed by servicing any pending interrupts via 29577c478bd9Sstevel@tonic-gate * sys_trap before returning back to the user mode from a fast trap 29587c478bd9Sstevel@tonic-gate * handler. The "done" instruction within a fast trap handler, which 29597c478bd9Sstevel@tonic-gate * runs entirely at TL=1 with interrupts disabled, is replaced with the 29607c478bd9Sstevel@tonic-gate * FAST_TRAP_DONE macro, which branches control to this fast_trap_done 29617c478bd9Sstevel@tonic-gate * entry point. 29627c478bd9Sstevel@tonic-gate * 29637c478bd9Sstevel@tonic-gate * We check for any pending interrupts here and force a sys_trap to 29647c478bd9Sstevel@tonic-gate * service those interrupts, if any. To minimize overhead, pending 29657c478bd9Sstevel@tonic-gate * interrupts are checked if the %tpc happens to be at 16K boundary, 29667c478bd9Sstevel@tonic-gate * which allows a malicious program to execute at most 4K consecutive 29677c478bd9Sstevel@tonic-gate * instructions before we service any pending interrupts. If a worst 29687c478bd9Sstevel@tonic-gate * case fast trap handler takes about 2 usec, then interrupts will be 29697c478bd9Sstevel@tonic-gate * blocked for at most 8 msec, less than a clock tick. 29707c478bd9Sstevel@tonic-gate * 29717c478bd9Sstevel@tonic-gate * For the cases where we don't know if the %tpc will cross a 16K 29727c478bd9Sstevel@tonic-gate * boundary, we can't use the above optimization and always process 29737c478bd9Sstevel@tonic-gate * any pending interrupts via fast_frap_done_chk_intr entry point. 29747c478bd9Sstevel@tonic-gate * 29757c478bd9Sstevel@tonic-gate * Entry Conditions: 29767c478bd9Sstevel@tonic-gate * %pstate am:0 priv:1 ie:0 29777c478bd9Sstevel@tonic-gate * globals are AG (not normal globals) 29787c478bd9Sstevel@tonic-gate */ 29797c478bd9Sstevel@tonic-gate 29807c478bd9Sstevel@tonic-gate .global fast_trap_done, fast_trap_done_chk_intr 29817c478bd9Sstevel@tonic-gatefast_trap_done: 29827c478bd9Sstevel@tonic-gate rdpr %tpc, %g5 29837c478bd9Sstevel@tonic-gate sethi %hi(0xffffc000), %g6 ! 1's complement of 0x3fff 29847c478bd9Sstevel@tonic-gate andncc %g5, %g6, %g0 ! check lower 14 bits of %tpc 29857c478bd9Sstevel@tonic-gate bz,a,pn %icc, 1f ! branch if zero (lower 32 bits only) 29867c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 29877c478bd9Sstevel@tonic-gate done 29887c478bd9Sstevel@tonic-gate 29899acbbeafSnn35248 ALTENTRY(fast_trap_done_check_interrupts) 29907c478bd9Sstevel@tonic-gatefast_trap_done_chk_intr: 29917c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 29927c478bd9Sstevel@tonic-gate 29937c478bd9Sstevel@tonic-gate1: rd SOFTINT, %g6 29947c478bd9Sstevel@tonic-gate and %g5, IRSR_BUSY, %g5 29957c478bd9Sstevel@tonic-gate orcc %g5, %g6, %g0 29967c478bd9Sstevel@tonic-gate bnz,pn %xcc, 2f ! branch if any pending intr 29977c478bd9Sstevel@tonic-gate nop 29987c478bd9Sstevel@tonic-gate done 29997c478bd9Sstevel@tonic-gate 30007c478bd9Sstevel@tonic-gate2: 30017c478bd9Sstevel@tonic-gate /* 30027c478bd9Sstevel@tonic-gate * We get here if there are any pending interrupts. 30037c478bd9Sstevel@tonic-gate * Adjust %tpc/%tnpc as we'll be resuming via "retry" 30047c478bd9Sstevel@tonic-gate * instruction. 30057c478bd9Sstevel@tonic-gate */ 30067c478bd9Sstevel@tonic-gate rdpr %tnpc, %g5 30077c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %tpc 30087c478bd9Sstevel@tonic-gate add %g5, 4, %g5 30097c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %tnpc 30107c478bd9Sstevel@tonic-gate 30117c478bd9Sstevel@tonic-gate /* 30127c478bd9Sstevel@tonic-gate * Force a dummy sys_trap call so that interrupts can be serviced. 30137c478bd9Sstevel@tonic-gate */ 30147c478bd9Sstevel@tonic-gate set fast_trap_dummy_call, %g1 30157c478bd9Sstevel@tonic-gate ba,pt %xcc, sys_trap 30167c478bd9Sstevel@tonic-gate mov -1, %g4 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gatefast_trap_dummy_call: 30197c478bd9Sstevel@tonic-gate retl 30207c478bd9Sstevel@tonic-gate nop 30217c478bd9Sstevel@tonic-gate 30229acbbeafSnn35248/* 302359f2ff5cSedp * Currently the brand syscall interposition code is not enabled by 302459f2ff5cSedp * default. Instead, when a branded zone is first booted the brand 302559f2ff5cSedp * infrastructure will patch the trap table so that the syscall 302659f2ff5cSedp * entry points are redirected to syscall_wrapper32 and syscall_wrapper 302759f2ff5cSedp * for ILP32 and LP64 syscalls respectively. this is done in 302859f2ff5cSedp * brand_plat_interposition_enable(). Note that the syscall wrappers 302959f2ff5cSedp * below do not collect any trap trace data since the syscall hot patch 303059f2ff5cSedp * points are reached after trap trace data has already been collected. 30319acbbeafSnn35248 */ 30329acbbeafSnn35248#define BRAND_CALLBACK(callback_id) \ 30334a75c0c1Sedp CPU_ADDR(%g2, %g1) /* load CPU struct addr to %g2 */ ;\ 30344a75c0c1Sedp ldn [%g2 + CPU_THREAD], %g3 /* load thread pointer */ ;\ 30354a75c0c1Sedp ldn [%g3 + T_PROCP], %g3 /* get proc pointer */ ;\ 30364a75c0c1Sedp ldn [%g3 + P_BRAND], %g3 /* get brand pointer */ ;\ 30374a75c0c1Sedp brz %g3, 1f /* No brand? No callback. */ ;\ 30389acbbeafSnn35248 nop ;\ 30394a75c0c1Sedp ldn [%g3 + B_MACHOPS], %g3 /* get machops list */ ;\ 30404a75c0c1Sedp ldn [%g3 + (callback_id << 3)], %g3 ;\ 30414a75c0c1Sedp brz %g3, 1f ;\ 30429acbbeafSnn35248 /* \ 30439acbbeafSnn35248 * This isn't pretty. We want a low-latency way for the callback \ 30449acbbeafSnn35248 * routine to decline to do anything. We just pass in an address \ 30459acbbeafSnn35248 * the routine can directly jmp back to, pretending that nothing \ 30469acbbeafSnn35248 * has happened. \ 30474a75c0c1Sedp * \ 30484a75c0c1Sedp * %g1: return address (where the brand handler jumps back to) \ 30494a75c0c1Sedp * %g2: address of CPU structure \ 30504a75c0c1Sedp * %g3: address of brand handler (where we will jump to) \ 30519acbbeafSnn35248 */ \ 30529acbbeafSnn35248 mov %pc, %g1 ;\ 30539acbbeafSnn35248 add %g1, 16, %g1 ;\ 30544a75c0c1Sedp jmp %g3 ;\ 30559acbbeafSnn35248 nop ;\ 30569acbbeafSnn352481: 30579acbbeafSnn35248 30589acbbeafSnn35248 ENTRY_NP(syscall_wrapper32) 30599acbbeafSnn35248 BRAND_CALLBACK(BRAND_CB_SYSCALL32) 30604a75c0c1Sedp SYSCALL_NOTT(syscall_trap32) 30619acbbeafSnn35248 SET_SIZE(syscall_wrapper32) 30629acbbeafSnn35248 30639acbbeafSnn35248 ENTRY_NP(syscall_wrapper) 30649acbbeafSnn35248 BRAND_CALLBACK(BRAND_CB_SYSCALL) 30654a75c0c1Sedp SYSCALL_NOTT(syscall_trap) 30669acbbeafSnn35248 SET_SIZE(syscall_wrapper) 30679acbbeafSnn35248 30687c478bd9Sstevel@tonic-gate#endif /* lint */ 3069