10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51640Spetede * Common Development and Distribution License (the "License"). 61640Spetede * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate/* 228803SJonathan.Haslam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 256127Ssm142603 260Sstevel@tonic-gate#if !defined(lint) 270Sstevel@tonic-gate#include "assym.h" 280Sstevel@tonic-gate#endif /* !lint */ 290Sstevel@tonic-gate#include <sys/asm_linkage.h> 300Sstevel@tonic-gate#include <sys/privregs.h> 310Sstevel@tonic-gate#include <sys/sun4asi.h> 321772Sjl139090#include <sys/spitregs.h> 330Sstevel@tonic-gate#include <sys/cheetahregs.h> 340Sstevel@tonic-gate#include <sys/machtrap.h> 350Sstevel@tonic-gate#include <sys/machthread.h> 362712Snn35248#include <sys/machbrand.h> 370Sstevel@tonic-gate#include <sys/pcb.h> 380Sstevel@tonic-gate#include <sys/pte.h> 390Sstevel@tonic-gate#include <sys/mmu.h> 400Sstevel@tonic-gate#include <sys/machpcb.h> 410Sstevel@tonic-gate#include <sys/async.h> 420Sstevel@tonic-gate#include <sys/intreg.h> 430Sstevel@tonic-gate#include <sys/scb.h> 440Sstevel@tonic-gate#include <sys/psr_compat.h> 450Sstevel@tonic-gate#include <sys/syscall.h> 460Sstevel@tonic-gate#include <sys/machparam.h> 470Sstevel@tonic-gate#include <sys/traptrace.h> 480Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 490Sstevel@tonic-gate#include <sys/archsystm.h> 500Sstevel@tonic-gate#include <sys/utrap.h> 510Sstevel@tonic-gate#include <sys/clock.h> 520Sstevel@tonic-gate#include <sys/intr.h> 530Sstevel@tonic-gate#include <sys/fpu/fpu_simulator.h> 540Sstevel@tonic-gate#include <vm/seg_spt.h> 550Sstevel@tonic-gate 560Sstevel@tonic-gate/* 570Sstevel@tonic-gate * WARNING: If you add a fast trap handler which can be invoked by a 580Sstevel@tonic-gate * non-privileged user, you may have to use the FAST_TRAP_DONE macro 590Sstevel@tonic-gate * instead of "done" instruction to return back to the user mode. See 600Sstevel@tonic-gate * comments for the "fast_trap_done" entry point for more information. 610Sstevel@tonic-gate * 620Sstevel@tonic-gate * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the 630Sstevel@tonic-gate * cases where you always want to process any pending interrupts before 640Sstevel@tonic-gate * returning back to the user mode. 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate#define FAST_TRAP_DONE \ 670Sstevel@tonic-gate ba,a fast_trap_done 680Sstevel@tonic-gate 690Sstevel@tonic-gate#define FAST_TRAP_DONE_CHK_INTR \ 700Sstevel@tonic-gate ba,a fast_trap_done_chk_intr 710Sstevel@tonic-gate 720Sstevel@tonic-gate/* 730Sstevel@tonic-gate * SPARC V9 Trap Table 740Sstevel@tonic-gate * 750Sstevel@tonic-gate * Most of the trap handlers are made from common building 760Sstevel@tonic-gate * blocks, and some are instantiated multiple times within 770Sstevel@tonic-gate * the trap table. So, I build a bunch of macros, then 780Sstevel@tonic-gate * populate the table using only the macros. 790Sstevel@tonic-gate * 800Sstevel@tonic-gate * Many macros branch to sys_trap. Its calling convention is: 810Sstevel@tonic-gate * %g1 kernel trap handler 820Sstevel@tonic-gate * %g2, %g3 args for above 830Sstevel@tonic-gate * %g4 desire %pil 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate 860Sstevel@tonic-gate#ifdef TRAPTRACE 870Sstevel@tonic-gate 880Sstevel@tonic-gate/* 890Sstevel@tonic-gate * Tracing macro. Adds two instructions if TRAPTRACE is defined. 900Sstevel@tonic-gate */ 910Sstevel@tonic-gate#define TT_TRACE(label) \ 920Sstevel@tonic-gate ba label ;\ 930Sstevel@tonic-gate rd %pc, %g7 940Sstevel@tonic-gate#define TT_TRACE_INS 2 950Sstevel@tonic-gate 960Sstevel@tonic-gate#define TT_TRACE_L(label) \ 970Sstevel@tonic-gate ba label ;\ 980Sstevel@tonic-gate rd %pc, %l4 ;\ 990Sstevel@tonic-gate clr %l4 1000Sstevel@tonic-gate#define TT_TRACE_L_INS 3 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate#else 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate#define TT_TRACE(label) 1050Sstevel@tonic-gate#define TT_TRACE_INS 0 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate#define TT_TRACE_L(label) 1080Sstevel@tonic-gate#define TT_TRACE_L_INS 0 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate#endif 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate/* 1130Sstevel@tonic-gate * This first set are funneled to trap() with %tt as the type. 1140Sstevel@tonic-gate * Trap will then either panic or send the user a signal. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate/* 1170Sstevel@tonic-gate * NOT is used for traps that just shouldn't happen. 1180Sstevel@tonic-gate * It comes in both single and quadruple flavors. 1190Sstevel@tonic-gate */ 1200Sstevel@tonic-gate#if !defined(lint) 1210Sstevel@tonic-gate .global trap 1220Sstevel@tonic-gate#endif /* !lint */ 1230Sstevel@tonic-gate#define NOT \ 1240Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1250Sstevel@tonic-gate set trap, %g1 ;\ 1260Sstevel@tonic-gate rdpr %tt, %g3 ;\ 1270Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1280Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1290Sstevel@tonic-gate .align 32 1300Sstevel@tonic-gate#define NOT4 NOT; NOT; NOT; NOT 1310Sstevel@tonic-gate/* 1320Sstevel@tonic-gate * RED is for traps that use the red mode handler. 1330Sstevel@tonic-gate * We should never see these either. 1340Sstevel@tonic-gate */ 1350Sstevel@tonic-gate#define RED NOT 1360Sstevel@tonic-gate/* 1370Sstevel@tonic-gate * BAD is used for trap vectors we don't have a kernel 1380Sstevel@tonic-gate * handler for. 1390Sstevel@tonic-gate * It also comes in single and quadruple versions. 1400Sstevel@tonic-gate */ 1410Sstevel@tonic-gate#define BAD NOT 1420Sstevel@tonic-gate#define BAD4 NOT4 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate#define DONE \ 1450Sstevel@tonic-gate done; \ 1460Sstevel@tonic-gate .align 32 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate/* 1490Sstevel@tonic-gate * TRAP vectors to the trap() function. 1500Sstevel@tonic-gate * It's main use is for user errors. 1510Sstevel@tonic-gate */ 1520Sstevel@tonic-gate#if !defined(lint) 1530Sstevel@tonic-gate .global trap 1540Sstevel@tonic-gate#endif /* !lint */ 1550Sstevel@tonic-gate#define TRAP(arg) \ 1560Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1570Sstevel@tonic-gate set trap, %g1 ;\ 1580Sstevel@tonic-gate mov arg, %g3 ;\ 1590Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1600Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1610Sstevel@tonic-gate .align 32 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate/* 1644141Sedp * SYSCALL is used for unsupported syscall interfaces (with 'which' 1654141Sedp * set to 'nosys') and legacy support of old SunOS 4.x syscalls (with 1664141Sedp * 'which' set to 'syscall_trap32'). 1674141Sedp * 1684141Sedp * The SYSCALL_TRAP* macros are used for syscall entry points. 1694141Sedp * SYSCALL_TRAP is used to support LP64 syscalls and SYSCALL_TRAP32 1704141Sedp * is used to support ILP32. Each macro can only be used once 1714141Sedp * since they each define a symbol. The symbols are used as hot patch 1724141Sedp * points by the brand infrastructure to dynamically enable and disable 1734141Sedp * brand syscall interposition. See the comments around BRAND_CALLBACK 1744141Sedp * and brand_plat_interposition_enable() for more information. 1750Sstevel@tonic-gate */ 1764127Sedp#define SYSCALL_NOTT(which) \ 1770Sstevel@tonic-gate set (which), %g1 ;\ 1780Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1790Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1800Sstevel@tonic-gate .align 32 1810Sstevel@tonic-gate 1824141Sedp#define SYSCALL(which) \ 1834141Sedp TT_TRACE(trace_gen) ;\ 1844141Sedp SYSCALL_NOTT(which) 1854141Sedp 1864141Sedp#define SYSCALL_TRAP32 \ 1874141Sedp TT_TRACE(trace_gen) ;\ 1884141Sedp ALTENTRY(syscall_trap32_patch_point) \ 1894141Sedp SYSCALL_NOTT(syscall_trap32) 1904141Sedp 1914141Sedp#define SYSCALL_TRAP \ 1924141Sedp TT_TRACE(trace_gen) ;\ 1934141Sedp ALTENTRY(syscall_trap_patch_point) \ 1944141Sedp SYSCALL_NOTT(syscall_trap) 1954141Sedp 1965414Smb158278#define FLUSHW(h_name) \ 1975414Smb158278 .global h_name ;\ 1985414Smb158278h_name: ;\ 1990Sstevel@tonic-gate set trap, %g1 ;\ 2000Sstevel@tonic-gate mov T_FLUSHW, %g3 ;\ 2010Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2020Sstevel@tonic-gate save ;\ 2030Sstevel@tonic-gate flushw ;\ 2040Sstevel@tonic-gate restore ;\ 2050Sstevel@tonic-gate FAST_TRAP_DONE ;\ 2060Sstevel@tonic-gate .align 32 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate/* 2090Sstevel@tonic-gate * GOTO just jumps to a label. 2100Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap. 2110Sstevel@tonic-gate */ 2120Sstevel@tonic-gate#define GOTO(label) \ 2130Sstevel@tonic-gate .global label ;\ 2140Sstevel@tonic-gate ba,a label ;\ 2150Sstevel@tonic-gate .empty ;\ 2160Sstevel@tonic-gate .align 32 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate/* 2190Sstevel@tonic-gate * GOTO_TT just jumps to a label. 2200Sstevel@tonic-gate * correctable ECC error traps at level 0 and 1 will use this macro. 2210Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap. 2220Sstevel@tonic-gate */ 2230Sstevel@tonic-gate#define GOTO_TT(label, ttlabel) \ 2240Sstevel@tonic-gate .global label ;\ 2250Sstevel@tonic-gate TT_TRACE(ttlabel) ;\ 2260Sstevel@tonic-gate ba,a label ;\ 2270Sstevel@tonic-gate .empty ;\ 2280Sstevel@tonic-gate .align 32 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate/* 2310Sstevel@tonic-gate * Privileged traps 2320Sstevel@tonic-gate * Takes breakpoint if privileged, calls trap() if not. 2330Sstevel@tonic-gate */ 2340Sstevel@tonic-gate#define PRIV(label) \ 2350Sstevel@tonic-gate rdpr %tstate, %g1 ;\ 2360Sstevel@tonic-gate btst TSTATE_PRIV, %g1 ;\ 2370Sstevel@tonic-gate bnz label ;\ 2380Sstevel@tonic-gate rdpr %tt, %g3 ;\ 2390Sstevel@tonic-gate set trap, %g1 ;\ 2400Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 2410Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2420Sstevel@tonic-gate .align 32 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate/* 2460Sstevel@tonic-gate * DTrace traps. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate#define DTRACE_PID \ 2490Sstevel@tonic-gate .global dtrace_pid_probe ;\ 2500Sstevel@tonic-gate set dtrace_pid_probe, %g1 ;\ 2510Sstevel@tonic-gate ba,pt %xcc, user_trap ;\ 2520Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2530Sstevel@tonic-gate .align 32 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate#define DTRACE_RETURN \ 2560Sstevel@tonic-gate .global dtrace_return_probe ;\ 2570Sstevel@tonic-gate set dtrace_return_probe, %g1 ;\ 2580Sstevel@tonic-gate ba,pt %xcc, user_trap ;\ 2590Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2600Sstevel@tonic-gate .align 32 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate/* 2630Sstevel@tonic-gate * REGISTER WINDOW MANAGEMENT MACROS 2640Sstevel@tonic-gate */ 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate/* 2670Sstevel@tonic-gate * various convenient units of padding 2680Sstevel@tonic-gate */ 2690Sstevel@tonic-gate#define SKIP(n) .skip 4*(n) 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate/* 2720Sstevel@tonic-gate * CLEAN_WINDOW is the simple handler for cleaning a register window. 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate#define CLEAN_WINDOW \ 2750Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 2760Sstevel@tonic-gate rdpr %cleanwin, %l0; inc %l0; wrpr %l0, %cleanwin ;\ 2770Sstevel@tonic-gate clr %l0; clr %l1; clr %l2; clr %l3 ;\ 2780Sstevel@tonic-gate clr %l4; clr %l5; clr %l6; clr %l7 ;\ 2790Sstevel@tonic-gate clr %o0; clr %o1; clr %o2; clr %o3 ;\ 2800Sstevel@tonic-gate clr %o4; clr %o5; clr %o6; clr %o7 ;\ 2810Sstevel@tonic-gate retry; .align 128 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate#if !defined(lint) 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate/* 2860Sstevel@tonic-gate * If we get an unresolved tlb miss while in a window handler, the fault 2870Sstevel@tonic-gate * handler will resume execution at the last instruction of the window 2880Sstevel@tonic-gate * hander, instead of delivering the fault to the kernel. Spill handlers 2890Sstevel@tonic-gate * use this to spill windows into the wbuf. 2900Sstevel@tonic-gate * 2910Sstevel@tonic-gate * The mixed handler works by checking %sp, and branching to the correct 2920Sstevel@tonic-gate * handler. This is done by branching back to label 1: for 32b frames, 2930Sstevel@tonic-gate * or label 2: for 64b frames; which implies the handler order is: 32b, 2940Sstevel@tonic-gate * 64b, mixed. The 1: and 2: labels are offset into the routines to 2950Sstevel@tonic-gate * allow the branchs' delay slots to contain useful instructions. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate/* 2990Sstevel@tonic-gate * SPILL_32bit spills a 32-bit-wide kernel register window. It 3000Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the 3010Sstevel@tonic-gate * same. The stack pointer is required to be eight-byte aligned even 3020Sstevel@tonic-gate * though this code only needs it to be four-byte aligned. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate#define SPILL_32bit(tail) \ 3050Sstevel@tonic-gate srl %sp, 0, %sp ;\ 3060Sstevel@tonic-gate1: st %l0, [%sp + 0] ;\ 3070Sstevel@tonic-gate st %l1, [%sp + 4] ;\ 3080Sstevel@tonic-gate st %l2, [%sp + 8] ;\ 3090Sstevel@tonic-gate st %l3, [%sp + 12] ;\ 3100Sstevel@tonic-gate st %l4, [%sp + 16] ;\ 3110Sstevel@tonic-gate st %l5, [%sp + 20] ;\ 3120Sstevel@tonic-gate st %l6, [%sp + 24] ;\ 3130Sstevel@tonic-gate st %l7, [%sp + 28] ;\ 3140Sstevel@tonic-gate st %i0, [%sp + 32] ;\ 3150Sstevel@tonic-gate st %i1, [%sp + 36] ;\ 3160Sstevel@tonic-gate st %i2, [%sp + 40] ;\ 3170Sstevel@tonic-gate st %i3, [%sp + 44] ;\ 3180Sstevel@tonic-gate st %i4, [%sp + 48] ;\ 3190Sstevel@tonic-gate st %i5, [%sp + 52] ;\ 3200Sstevel@tonic-gate st %i6, [%sp + 56] ;\ 3210Sstevel@tonic-gate st %i7, [%sp + 60] ;\ 3220Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3230Sstevel@tonic-gate saved ;\ 3240Sstevel@tonic-gate retry ;\ 3250Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 3260Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3270Sstevel@tonic-gate .empty 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate/* 3300Sstevel@tonic-gate * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit 3310Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 3320Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 3330Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte 3340Sstevel@tonic-gate * aligned. 3350Sstevel@tonic-gate */ 3360Sstevel@tonic-gate#define SPILL_32bit_asi(asi_num, tail) \ 3370Sstevel@tonic-gate srl %sp, 0, %sp ;\ 3380Sstevel@tonic-gate1: sta %l0, [%sp + %g0]asi_num ;\ 3390Sstevel@tonic-gate mov 4, %g1 ;\ 3400Sstevel@tonic-gate sta %l1, [%sp + %g1]asi_num ;\ 3410Sstevel@tonic-gate mov 8, %g2 ;\ 3420Sstevel@tonic-gate sta %l2, [%sp + %g2]asi_num ;\ 3430Sstevel@tonic-gate mov 12, %g3 ;\ 3440Sstevel@tonic-gate sta %l3, [%sp + %g3]asi_num ;\ 3450Sstevel@tonic-gate add %sp, 16, %g4 ;\ 3460Sstevel@tonic-gate sta %l4, [%g4 + %g0]asi_num ;\ 3470Sstevel@tonic-gate sta %l5, [%g4 + %g1]asi_num ;\ 3480Sstevel@tonic-gate sta %l6, [%g4 + %g2]asi_num ;\ 3490Sstevel@tonic-gate sta %l7, [%g4 + %g3]asi_num ;\ 3500Sstevel@tonic-gate add %g4, 16, %g4 ;\ 3510Sstevel@tonic-gate sta %i0, [%g4 + %g0]asi_num ;\ 3520Sstevel@tonic-gate sta %i1, [%g4 + %g1]asi_num ;\ 3530Sstevel@tonic-gate sta %i2, [%g4 + %g2]asi_num ;\ 3540Sstevel@tonic-gate sta %i3, [%g4 + %g3]asi_num ;\ 3550Sstevel@tonic-gate add %g4, 16, %g4 ;\ 3560Sstevel@tonic-gate sta %i4, [%g4 + %g0]asi_num ;\ 3570Sstevel@tonic-gate sta %i5, [%g4 + %g1]asi_num ;\ 3580Sstevel@tonic-gate sta %i6, [%g4 + %g2]asi_num ;\ 3590Sstevel@tonic-gate sta %i7, [%g4 + %g3]asi_num ;\ 3600Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3610Sstevel@tonic-gate saved ;\ 3620Sstevel@tonic-gate retry ;\ 3630Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 3640Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3650Sstevel@tonic-gate .empty 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate/* 3680Sstevel@tonic-gate * SPILL_32bit_tt1 spills a 32-bit-wide register window into a 32-bit 3690Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 3700Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 3710Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 3720Sstevel@tonic-gate * pointer is required to be eight-byte aligned even though this code 3730Sstevel@tonic-gate * only needs it to be four-byte aligned. 3740Sstevel@tonic-gate */ 3750Sstevel@tonic-gate#define SPILL_32bit_tt1(asi_num, tail) \ 3760Sstevel@tonic-gate mov asi_num, %asi ;\ 3770Sstevel@tonic-gate1: srl %sp, 0, %sp ;\ 3780Sstevel@tonic-gate sta %l0, [%sp + 0]%asi ;\ 3790Sstevel@tonic-gate sta %l1, [%sp + 4]%asi ;\ 3800Sstevel@tonic-gate sta %l2, [%sp + 8]%asi ;\ 3810Sstevel@tonic-gate sta %l3, [%sp + 12]%asi ;\ 3820Sstevel@tonic-gate sta %l4, [%sp + 16]%asi ;\ 3830Sstevel@tonic-gate sta %l5, [%sp + 20]%asi ;\ 3840Sstevel@tonic-gate sta %l6, [%sp + 24]%asi ;\ 3850Sstevel@tonic-gate sta %l7, [%sp + 28]%asi ;\ 3860Sstevel@tonic-gate sta %i0, [%sp + 32]%asi ;\ 3870Sstevel@tonic-gate sta %i1, [%sp + 36]%asi ;\ 3880Sstevel@tonic-gate sta %i2, [%sp + 40]%asi ;\ 3890Sstevel@tonic-gate sta %i3, [%sp + 44]%asi ;\ 3900Sstevel@tonic-gate sta %i4, [%sp + 48]%asi ;\ 3910Sstevel@tonic-gate sta %i5, [%sp + 52]%asi ;\ 3920Sstevel@tonic-gate sta %i6, [%sp + 56]%asi ;\ 3930Sstevel@tonic-gate sta %i7, [%sp + 60]%asi ;\ 3940Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3950Sstevel@tonic-gate saved ;\ 3960Sstevel@tonic-gate retry ;\ 3970Sstevel@tonic-gate SKIP(31-20-TT_TRACE_L_INS) ;\ 3980Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3990Sstevel@tonic-gate .empty 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate/* 4030Sstevel@tonic-gate * FILL_32bit fills a 32-bit-wide kernel register window. It assumes 4040Sstevel@tonic-gate * that the kernel context and the nucleus context are the same. The 4050Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned even though this 4060Sstevel@tonic-gate * code only needs it to be four-byte aligned. 4070Sstevel@tonic-gate */ 4080Sstevel@tonic-gate#define FILL_32bit(tail) \ 4090Sstevel@tonic-gate srl %sp, 0, %sp ;\ 4100Sstevel@tonic-gate1: TT_TRACE_L(trace_win) ;\ 4110Sstevel@tonic-gate ld [%sp + 0], %l0 ;\ 4120Sstevel@tonic-gate ld [%sp + 4], %l1 ;\ 4130Sstevel@tonic-gate ld [%sp + 8], %l2 ;\ 4140Sstevel@tonic-gate ld [%sp + 12], %l3 ;\ 4150Sstevel@tonic-gate ld [%sp + 16], %l4 ;\ 4160Sstevel@tonic-gate ld [%sp + 20], %l5 ;\ 4170Sstevel@tonic-gate ld [%sp + 24], %l6 ;\ 4180Sstevel@tonic-gate ld [%sp + 28], %l7 ;\ 4190Sstevel@tonic-gate ld [%sp + 32], %i0 ;\ 4200Sstevel@tonic-gate ld [%sp + 36], %i1 ;\ 4210Sstevel@tonic-gate ld [%sp + 40], %i2 ;\ 4220Sstevel@tonic-gate ld [%sp + 44], %i3 ;\ 4230Sstevel@tonic-gate ld [%sp + 48], %i4 ;\ 4240Sstevel@tonic-gate ld [%sp + 52], %i5 ;\ 4250Sstevel@tonic-gate ld [%sp + 56], %i6 ;\ 4260Sstevel@tonic-gate ld [%sp + 60], %i7 ;\ 4270Sstevel@tonic-gate restored ;\ 4280Sstevel@tonic-gate retry ;\ 4290Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 4300Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 4310Sstevel@tonic-gate .empty 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate/* 4340Sstevel@tonic-gate * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit 4350Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 4360Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 4370Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte 4380Sstevel@tonic-gate * aligned. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate#define FILL_32bit_asi(asi_num, tail) \ 4410Sstevel@tonic-gate srl %sp, 0, %sp ;\ 4420Sstevel@tonic-gate1: TT_TRACE_L(trace_win) ;\ 4430Sstevel@tonic-gate mov 4, %g1 ;\ 4440Sstevel@tonic-gate lda [%sp + %g0]asi_num, %l0 ;\ 4450Sstevel@tonic-gate mov 8, %g2 ;\ 4460Sstevel@tonic-gate lda [%sp + %g1]asi_num, %l1 ;\ 4470Sstevel@tonic-gate mov 12, %g3 ;\ 4480Sstevel@tonic-gate lda [%sp + %g2]asi_num, %l2 ;\ 4490Sstevel@tonic-gate lda [%sp + %g3]asi_num, %l3 ;\ 4500Sstevel@tonic-gate add %sp, 16, %g4 ;\ 4510Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %l4 ;\ 4520Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %l5 ;\ 4530Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %l6 ;\ 4540Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %l7 ;\ 4550Sstevel@tonic-gate add %g4, 16, %g4 ;\ 4560Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %i0 ;\ 4570Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %i1 ;\ 4580Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %i2 ;\ 4590Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %i3 ;\ 4600Sstevel@tonic-gate add %g4, 16, %g4 ;\ 4610Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %i4 ;\ 4620Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %i5 ;\ 4630Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %i6 ;\ 4640Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %i7 ;\ 4650Sstevel@tonic-gate restored ;\ 4660Sstevel@tonic-gate retry ;\ 4670Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 4680Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 4690Sstevel@tonic-gate .empty 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate/* 4720Sstevel@tonic-gate * FILL_32bit_tt1 fills a 32-bit-wide register window from a 32-bit 4730Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 4740Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 4750Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 4760Sstevel@tonic-gate * pointer is required to be eight-byte aligned even though this code 4770Sstevel@tonic-gate * only needs it to be four-byte aligned. 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate#define FILL_32bit_tt1(asi_num, tail) \ 4800Sstevel@tonic-gate mov asi_num, %asi ;\ 4810Sstevel@tonic-gate1: srl %sp, 0, %sp ;\ 4820Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 4830Sstevel@tonic-gate lda [%sp + 0]%asi, %l0 ;\ 4840Sstevel@tonic-gate lda [%sp + 4]%asi, %l1 ;\ 4850Sstevel@tonic-gate lda [%sp + 8]%asi, %l2 ;\ 4860Sstevel@tonic-gate lda [%sp + 12]%asi, %l3 ;\ 4870Sstevel@tonic-gate lda [%sp + 16]%asi, %l4 ;\ 4880Sstevel@tonic-gate lda [%sp + 20]%asi, %l5 ;\ 4890Sstevel@tonic-gate lda [%sp + 24]%asi, %l6 ;\ 4900Sstevel@tonic-gate lda [%sp + 28]%asi, %l7 ;\ 4910Sstevel@tonic-gate lda [%sp + 32]%asi, %i0 ;\ 4920Sstevel@tonic-gate lda [%sp + 36]%asi, %i1 ;\ 4930Sstevel@tonic-gate lda [%sp + 40]%asi, %i2 ;\ 4940Sstevel@tonic-gate lda [%sp + 44]%asi, %i3 ;\ 4950Sstevel@tonic-gate lda [%sp + 48]%asi, %i4 ;\ 4960Sstevel@tonic-gate lda [%sp + 52]%asi, %i5 ;\ 4970Sstevel@tonic-gate lda [%sp + 56]%asi, %i6 ;\ 4980Sstevel@tonic-gate lda [%sp + 60]%asi, %i7 ;\ 4990Sstevel@tonic-gate restored ;\ 5000Sstevel@tonic-gate retry ;\ 5010Sstevel@tonic-gate SKIP(31-20-TT_TRACE_L_INS) ;\ 5020Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 5030Sstevel@tonic-gate .empty 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate/* 5070Sstevel@tonic-gate * SPILL_64bit spills a 64-bit-wide kernel register window. It 5080Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the 5090Sstevel@tonic-gate * same. The stack pointer is required to be eight-byte aligned. 5100Sstevel@tonic-gate */ 5110Sstevel@tonic-gate#define SPILL_64bit(tail) \ 5120Sstevel@tonic-gate2: stx %l0, [%sp + V9BIAS64 + 0] ;\ 5130Sstevel@tonic-gate stx %l1, [%sp + V9BIAS64 + 8] ;\ 5140Sstevel@tonic-gate stx %l2, [%sp + V9BIAS64 + 16] ;\ 5150Sstevel@tonic-gate stx %l3, [%sp + V9BIAS64 + 24] ;\ 5160Sstevel@tonic-gate stx %l4, [%sp + V9BIAS64 + 32] ;\ 5170Sstevel@tonic-gate stx %l5, [%sp + V9BIAS64 + 40] ;\ 5180Sstevel@tonic-gate stx %l6, [%sp + V9BIAS64 + 48] ;\ 5190Sstevel@tonic-gate stx %l7, [%sp + V9BIAS64 + 56] ;\ 5200Sstevel@tonic-gate stx %i0, [%sp + V9BIAS64 + 64] ;\ 5210Sstevel@tonic-gate stx %i1, [%sp + V9BIAS64 + 72] ;\ 5220Sstevel@tonic-gate stx %i2, [%sp + V9BIAS64 + 80] ;\ 5230Sstevel@tonic-gate stx %i3, [%sp + V9BIAS64 + 88] ;\ 5240Sstevel@tonic-gate stx %i4, [%sp + V9BIAS64 + 96] ;\ 5250Sstevel@tonic-gate stx %i5, [%sp + V9BIAS64 + 104] ;\ 5260Sstevel@tonic-gate stx %i6, [%sp + V9BIAS64 + 112] ;\ 5270Sstevel@tonic-gate stx %i7, [%sp + V9BIAS64 + 120] ;\ 5280Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5290Sstevel@tonic-gate saved ;\ 5300Sstevel@tonic-gate retry ;\ 5310Sstevel@tonic-gate SKIP(31-18-TT_TRACE_L_INS) ;\ 5320Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5330Sstevel@tonic-gate .empty 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate/* 5360Sstevel@tonic-gate * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit 5370Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 5380Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 5390Sstevel@tonic-gate * aligned. 5400Sstevel@tonic-gate */ 5410Sstevel@tonic-gate#define SPILL_64bit_asi(asi_num, tail) \ 5420Sstevel@tonic-gate mov 0 + V9BIAS64, %g1 ;\ 5430Sstevel@tonic-gate2: stxa %l0, [%sp + %g1]asi_num ;\ 5440Sstevel@tonic-gate mov 8 + V9BIAS64, %g2 ;\ 5450Sstevel@tonic-gate stxa %l1, [%sp + %g2]asi_num ;\ 5460Sstevel@tonic-gate mov 16 + V9BIAS64, %g3 ;\ 5470Sstevel@tonic-gate stxa %l2, [%sp + %g3]asi_num ;\ 5480Sstevel@tonic-gate mov 24 + V9BIAS64, %g4 ;\ 5490Sstevel@tonic-gate stxa %l3, [%sp + %g4]asi_num ;\ 5500Sstevel@tonic-gate add %sp, 32, %g5 ;\ 5510Sstevel@tonic-gate stxa %l4, [%g5 + %g1]asi_num ;\ 5520Sstevel@tonic-gate stxa %l5, [%g5 + %g2]asi_num ;\ 5530Sstevel@tonic-gate stxa %l6, [%g5 + %g3]asi_num ;\ 5540Sstevel@tonic-gate stxa %l7, [%g5 + %g4]asi_num ;\ 5550Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5560Sstevel@tonic-gate stxa %i0, [%g5 + %g1]asi_num ;\ 5570Sstevel@tonic-gate stxa %i1, [%g5 + %g2]asi_num ;\ 5580Sstevel@tonic-gate stxa %i2, [%g5 + %g3]asi_num ;\ 5590Sstevel@tonic-gate stxa %i3, [%g5 + %g4]asi_num ;\ 5600Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5610Sstevel@tonic-gate stxa %i4, [%g5 + %g1]asi_num ;\ 5620Sstevel@tonic-gate stxa %i5, [%g5 + %g2]asi_num ;\ 5630Sstevel@tonic-gate stxa %i6, [%g5 + %g3]asi_num ;\ 5640Sstevel@tonic-gate stxa %i7, [%g5 + %g4]asi_num ;\ 5650Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5660Sstevel@tonic-gate saved ;\ 5670Sstevel@tonic-gate retry ;\ 5680Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 5690Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5700Sstevel@tonic-gate .empty 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate/* 5730Sstevel@tonic-gate * SPILL_64bit_tt1 spills a 64-bit-wide register window into a 64-bit 5740Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 5750Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 5760Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 5770Sstevel@tonic-gate * pointer is required to be eight-byte aligned. 5780Sstevel@tonic-gate */ 5790Sstevel@tonic-gate#define SPILL_64bit_tt1(asi_num, tail) \ 5800Sstevel@tonic-gate mov asi_num, %asi ;\ 5810Sstevel@tonic-gate2: stxa %l0, [%sp + V9BIAS64 + 0]%asi ;\ 5820Sstevel@tonic-gate stxa %l1, [%sp + V9BIAS64 + 8]%asi ;\ 5830Sstevel@tonic-gate stxa %l2, [%sp + V9BIAS64 + 16]%asi ;\ 5840Sstevel@tonic-gate stxa %l3, [%sp + V9BIAS64 + 24]%asi ;\ 5850Sstevel@tonic-gate stxa %l4, [%sp + V9BIAS64 + 32]%asi ;\ 5860Sstevel@tonic-gate stxa %l5, [%sp + V9BIAS64 + 40]%asi ;\ 5870Sstevel@tonic-gate stxa %l6, [%sp + V9BIAS64 + 48]%asi ;\ 5880Sstevel@tonic-gate stxa %l7, [%sp + V9BIAS64 + 56]%asi ;\ 5890Sstevel@tonic-gate stxa %i0, [%sp + V9BIAS64 + 64]%asi ;\ 5900Sstevel@tonic-gate stxa %i1, [%sp + V9BIAS64 + 72]%asi ;\ 5910Sstevel@tonic-gate stxa %i2, [%sp + V9BIAS64 + 80]%asi ;\ 5920Sstevel@tonic-gate stxa %i3, [%sp + V9BIAS64 + 88]%asi ;\ 5930Sstevel@tonic-gate stxa %i4, [%sp + V9BIAS64 + 96]%asi ;\ 5940Sstevel@tonic-gate stxa %i5, [%sp + V9BIAS64 + 104]%asi ;\ 5950Sstevel@tonic-gate stxa %i6, [%sp + V9BIAS64 + 112]%asi ;\ 5960Sstevel@tonic-gate stxa %i7, [%sp + V9BIAS64 + 120]%asi ;\ 5970Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5980Sstevel@tonic-gate saved ;\ 5990Sstevel@tonic-gate retry ;\ 6000Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 6010Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 6020Sstevel@tonic-gate .empty 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate/* 6060Sstevel@tonic-gate * FILL_64bit fills a 64-bit-wide kernel register window. It assumes 6070Sstevel@tonic-gate * that the kernel context and the nucleus context are the same. The 6080Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned. 6090Sstevel@tonic-gate */ 6100Sstevel@tonic-gate#define FILL_64bit(tail) \ 6110Sstevel@tonic-gate2: TT_TRACE_L(trace_win) ;\ 6120Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 0], %l0 ;\ 6130Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 8], %l1 ;\ 6140Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 16], %l2 ;\ 6150Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 24], %l3 ;\ 6160Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 32], %l4 ;\ 6170Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 40], %l5 ;\ 6180Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 48], %l6 ;\ 6190Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 56], %l7 ;\ 6200Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 64], %i0 ;\ 6210Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 72], %i1 ;\ 6220Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 80], %i2 ;\ 6230Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 88], %i3 ;\ 6240Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 96], %i4 ;\ 6250Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 104], %i5 ;\ 6260Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 112], %i6 ;\ 6270Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 120], %i7 ;\ 6280Sstevel@tonic-gate restored ;\ 6290Sstevel@tonic-gate retry ;\ 6300Sstevel@tonic-gate SKIP(31-18-TT_TRACE_L_INS) ;\ 6310Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 6320Sstevel@tonic-gate .empty 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate/* 6350Sstevel@tonic-gate * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit 6360Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 6370Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 6384127Sedp * aligned. 6390Sstevel@tonic-gate */ 6400Sstevel@tonic-gate#define FILL_64bit_asi(asi_num, tail) \ 6410Sstevel@tonic-gate mov V9BIAS64 + 0, %g1 ;\ 6420Sstevel@tonic-gate2: TT_TRACE_L(trace_win) ;\ 6430Sstevel@tonic-gate ldxa [%sp + %g1]asi_num, %l0 ;\ 6440Sstevel@tonic-gate mov V9BIAS64 + 8, %g2 ;\ 6450Sstevel@tonic-gate ldxa [%sp + %g2]asi_num, %l1 ;\ 6460Sstevel@tonic-gate mov V9BIAS64 + 16, %g3 ;\ 6470Sstevel@tonic-gate ldxa [%sp + %g3]asi_num, %l2 ;\ 6480Sstevel@tonic-gate mov V9BIAS64 + 24, %g4 ;\ 6490Sstevel@tonic-gate ldxa [%sp + %g4]asi_num, %l3 ;\ 6500Sstevel@tonic-gate add %sp, 32, %g5 ;\ 6510Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %l4 ;\ 6520Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %l5 ;\ 6530Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %l6 ;\ 6540Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %l7 ;\ 6550Sstevel@tonic-gate add %g5, 32, %g5 ;\ 6560Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %i0 ;\ 6570Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %i1 ;\ 6580Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %i2 ;\ 6590Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %i3 ;\ 6600Sstevel@tonic-gate add %g5, 32, %g5 ;\ 6610Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %i4 ;\ 6620Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %i5 ;\ 6630Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %i6 ;\ 6640Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %i7 ;\ 6650Sstevel@tonic-gate restored ;\ 6660Sstevel@tonic-gate retry ;\ 6670Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 6680Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 6690Sstevel@tonic-gate .empty 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate/* 6720Sstevel@tonic-gate * FILL_64bit_tt1 fills a 64-bit-wide register window from a 64-bit 6730Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 6740Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and 6750Sstevel@tonic-gate * where we don't want to use unnecessary registers. The stack 6760Sstevel@tonic-gate * pointer is required to be eight-byte aligned. 6770Sstevel@tonic-gate */ 6780Sstevel@tonic-gate#define FILL_64bit_tt1(asi_num, tail) \ 6790Sstevel@tonic-gate mov asi_num, %asi ;\ 6800Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 6810Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 0]%asi, %l0 ;\ 6820Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 8]%asi, %l1 ;\ 6830Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 16]%asi, %l2 ;\ 6840Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 24]%asi, %l3 ;\ 6850Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 32]%asi, %l4 ;\ 6860Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 40]%asi, %l5 ;\ 6870Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 48]%asi, %l6 ;\ 6880Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 56]%asi, %l7 ;\ 6890Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 64]%asi, %i0 ;\ 6900Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 72]%asi, %i1 ;\ 6910Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 80]%asi, %i2 ;\ 6920Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 88]%asi, %i3 ;\ 6930Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 96]%asi, %i4 ;\ 6940Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 104]%asi, %i5 ;\ 6950Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 112]%asi, %i6 ;\ 6960Sstevel@tonic-gate ldxa [%sp + V9BIAS64 + 120]%asi, %i7 ;\ 6970Sstevel@tonic-gate restored ;\ 6980Sstevel@tonic-gate retry ;\ 6990Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 7000Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 7010Sstevel@tonic-gate .empty 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate#endif /* !lint */ 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate/* 7060Sstevel@tonic-gate * SPILL_mixed spills either size window, depending on 7070Sstevel@tonic-gate * whether %sp is even or odd, to a 32-bit address space. 7080Sstevel@tonic-gate * This may only be used in conjunction with SPILL_32bit/ 7090Sstevel@tonic-gate * SPILL_64bit. New versions of SPILL_mixed_{tt1,asi} would be 7100Sstevel@tonic-gate * needed for use with SPILL_{32,64}bit_{tt1,asi}. Particular 7110Sstevel@tonic-gate * attention should be paid to the instructions that belong 7120Sstevel@tonic-gate * in the delay slots of the branches depending on the type 7130Sstevel@tonic-gate * of spill handler being branched to. 7140Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd. 7150Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel. 7160Sstevel@tonic-gate */ 7170Sstevel@tonic-gate#define SPILL_mixed \ 7180Sstevel@tonic-gate btst 1, %sp ;\ 7190Sstevel@tonic-gate bz,a,pt %xcc, 1b ;\ 7200Sstevel@tonic-gate srl %sp, 0, %sp ;\ 7210Sstevel@tonic-gate ba,pt %xcc, 2b ;\ 7220Sstevel@tonic-gate nop ;\ 7230Sstevel@tonic-gate .align 128 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate/* 7260Sstevel@tonic-gate * FILL_mixed(ASI) fills either size window, depending on 7270Sstevel@tonic-gate * whether %sp is even or odd, from a 32-bit address space. 7280Sstevel@tonic-gate * This may only be used in conjunction with FILL_32bit/ 7290Sstevel@tonic-gate * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be 7300Sstevel@tonic-gate * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular 7310Sstevel@tonic-gate * attention should be paid to the instructions that belong 7320Sstevel@tonic-gate * in the delay slots of the branches depending on the type 7330Sstevel@tonic-gate * of fill handler being branched to. 7340Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd. 7350Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel. 7360Sstevel@tonic-gate */ 7370Sstevel@tonic-gate#define FILL_mixed \ 7380Sstevel@tonic-gate btst 1, %sp ;\ 7390Sstevel@tonic-gate bz,a,pt %xcc, 1b ;\ 7400Sstevel@tonic-gate srl %sp, 0, %sp ;\ 7410Sstevel@tonic-gate ba,pt %xcc, 2b ;\ 7420Sstevel@tonic-gate nop ;\ 7430Sstevel@tonic-gate .align 128 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate/* 7470Sstevel@tonic-gate * SPILL_32clean/SPILL_64clean spill 32-bit and 64-bit register windows, 7480Sstevel@tonic-gate * respectively, into the address space via the designated asi. The 7490Sstevel@tonic-gate * unbiased stack pointer is required to be eight-byte aligned (even for 7500Sstevel@tonic-gate * the 32-bit case even though this code does not require such strict 7510Sstevel@tonic-gate * alignment). 7520Sstevel@tonic-gate * 7530Sstevel@tonic-gate * With SPARC v9 the spill trap takes precedence over the cleanwin trap 7540Sstevel@tonic-gate * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save 7550Sstevel@tonic-gate * will cause cwp + 2 to be spilled but will not clean cwp + 1. That 7560Sstevel@tonic-gate * window may contain kernel data so in user_rtt we set wstate to call 7570Sstevel@tonic-gate * these spill handlers on the first user spill trap. These handler then 7580Sstevel@tonic-gate * spill the appropriate window but also back up a window and clean the 7590Sstevel@tonic-gate * window that didn't get a cleanwin trap. 7600Sstevel@tonic-gate */ 7610Sstevel@tonic-gate#define SPILL_32clean(asi_num, tail) \ 7620Sstevel@tonic-gate srl %sp, 0, %sp ;\ 7630Sstevel@tonic-gate sta %l0, [%sp + %g0]asi_num ;\ 7640Sstevel@tonic-gate mov 4, %g1 ;\ 7650Sstevel@tonic-gate sta %l1, [%sp + %g1]asi_num ;\ 7660Sstevel@tonic-gate mov 8, %g2 ;\ 7670Sstevel@tonic-gate sta %l2, [%sp + %g2]asi_num ;\ 7680Sstevel@tonic-gate mov 12, %g3 ;\ 7690Sstevel@tonic-gate sta %l3, [%sp + %g3]asi_num ;\ 7700Sstevel@tonic-gate add %sp, 16, %g4 ;\ 7710Sstevel@tonic-gate sta %l4, [%g4 + %g0]asi_num ;\ 7720Sstevel@tonic-gate sta %l5, [%g4 + %g1]asi_num ;\ 7730Sstevel@tonic-gate sta %l6, [%g4 + %g2]asi_num ;\ 7740Sstevel@tonic-gate sta %l7, [%g4 + %g3]asi_num ;\ 7750Sstevel@tonic-gate add %g4, 16, %g4 ;\ 7760Sstevel@tonic-gate sta %i0, [%g4 + %g0]asi_num ;\ 7770Sstevel@tonic-gate sta %i1, [%g4 + %g1]asi_num ;\ 7780Sstevel@tonic-gate sta %i2, [%g4 + %g2]asi_num ;\ 7790Sstevel@tonic-gate sta %i3, [%g4 + %g3]asi_num ;\ 7800Sstevel@tonic-gate add %g4, 16, %g4 ;\ 7810Sstevel@tonic-gate sta %i4, [%g4 + %g0]asi_num ;\ 7820Sstevel@tonic-gate sta %i5, [%g4 + %g1]asi_num ;\ 7830Sstevel@tonic-gate sta %i6, [%g4 + %g2]asi_num ;\ 7840Sstevel@tonic-gate sta %i7, [%g4 + %g3]asi_num ;\ 7850Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 7860Sstevel@tonic-gate b .spill_clean ;\ 7870Sstevel@tonic-gate mov WSTATE_USER32, %g7 ;\ 7880Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 7890Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 7900Sstevel@tonic-gate .empty 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate#define SPILL_64clean(asi_num, tail) \ 7930Sstevel@tonic-gate mov 0 + V9BIAS64, %g1 ;\ 7940Sstevel@tonic-gate stxa %l0, [%sp + %g1]asi_num ;\ 7950Sstevel@tonic-gate mov 8 + V9BIAS64, %g2 ;\ 7960Sstevel@tonic-gate stxa %l1, [%sp + %g2]asi_num ;\ 7970Sstevel@tonic-gate mov 16 + V9BIAS64, %g3 ;\ 7980Sstevel@tonic-gate stxa %l2, [%sp + %g3]asi_num ;\ 7990Sstevel@tonic-gate mov 24 + V9BIAS64, %g4 ;\ 8000Sstevel@tonic-gate stxa %l3, [%sp + %g4]asi_num ;\ 8010Sstevel@tonic-gate add %sp, 32, %g5 ;\ 8020Sstevel@tonic-gate stxa %l4, [%g5 + %g1]asi_num ;\ 8030Sstevel@tonic-gate stxa %l5, [%g5 + %g2]asi_num ;\ 8040Sstevel@tonic-gate stxa %l6, [%g5 + %g3]asi_num ;\ 8050Sstevel@tonic-gate stxa %l7, [%g5 + %g4]asi_num ;\ 8060Sstevel@tonic-gate add %g5, 32, %g5 ;\ 8070Sstevel@tonic-gate stxa %i0, [%g5 + %g1]asi_num ;\ 8080Sstevel@tonic-gate stxa %i1, [%g5 + %g2]asi_num ;\ 8090Sstevel@tonic-gate stxa %i2, [%g5 + %g3]asi_num ;\ 8100Sstevel@tonic-gate stxa %i3, [%g5 + %g4]asi_num ;\ 8110Sstevel@tonic-gate add %g5, 32, %g5 ;\ 8120Sstevel@tonic-gate stxa %i4, [%g5 + %g1]asi_num ;\ 8130Sstevel@tonic-gate stxa %i5, [%g5 + %g2]asi_num ;\ 8140Sstevel@tonic-gate stxa %i6, [%g5 + %g3]asi_num ;\ 8150Sstevel@tonic-gate stxa %i7, [%g5 + %g4]asi_num ;\ 8160Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 8170Sstevel@tonic-gate b .spill_clean ;\ 8180Sstevel@tonic-gate mov WSTATE_USER64, %g7 ;\ 8190Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 8200Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 8210Sstevel@tonic-gate .empty 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate/* 8250Sstevel@tonic-gate * Floating point disabled. 8260Sstevel@tonic-gate */ 8270Sstevel@tonic-gate#define FP_DISABLED_TRAP \ 8280Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8290Sstevel@tonic-gate ba,pt %xcc,.fp_disabled ;\ 8300Sstevel@tonic-gate nop ;\ 8310Sstevel@tonic-gate .align 32 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate/* 8340Sstevel@tonic-gate * Floating point exceptions. 8350Sstevel@tonic-gate */ 8360Sstevel@tonic-gate#define FP_IEEE_TRAP \ 8370Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8380Sstevel@tonic-gate ba,pt %xcc,.fp_ieee_exception ;\ 8390Sstevel@tonic-gate nop ;\ 8400Sstevel@tonic-gate .align 32 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate#define FP_TRAP \ 8430Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8440Sstevel@tonic-gate ba,pt %xcc,.fp_exception ;\ 8450Sstevel@tonic-gate nop ;\ 8460Sstevel@tonic-gate .align 32 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate#if !defined(lint) 8490Sstevel@tonic-gate/* 8500Sstevel@tonic-gate * asynchronous traps at level 0 and level 1 8510Sstevel@tonic-gate * 8520Sstevel@tonic-gate * The first instruction must be a membar for UltraSPARC-III 8530Sstevel@tonic-gate * to stop RED state entry if the store queue has many 8540Sstevel@tonic-gate * pending bad stores (PRM, Chapter 11). 8550Sstevel@tonic-gate */ 8561772Sjl139090#define ASYNC_TRAP(ttype, ttlabel, table_name)\ 8571772Sjl139090 .global table_name ;\ 8581772Sjl139090table_name: ;\ 8590Sstevel@tonic-gate membar #Sync ;\ 8600Sstevel@tonic-gate TT_TRACE(ttlabel) ;\ 8610Sstevel@tonic-gate ba async_err ;\ 8620Sstevel@tonic-gate mov ttype, %g5 ;\ 8630Sstevel@tonic-gate .align 32 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate/* 8660Sstevel@tonic-gate * Defaults to BAD entry, but establishes label to be used for 8670Sstevel@tonic-gate * architecture-specific overwrite of trap table entry. 8680Sstevel@tonic-gate */ 8690Sstevel@tonic-gate#define LABELED_BAD(table_name) \ 8700Sstevel@tonic-gate .global table_name ;\ 8710Sstevel@tonic-gatetable_name: ;\ 8720Sstevel@tonic-gate BAD 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate#endif /* !lint */ 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate/* 8770Sstevel@tonic-gate * illegal instruction trap 8780Sstevel@tonic-gate */ 8790Sstevel@tonic-gate#define ILLTRAP_INSTR \ 8800Sstevel@tonic-gate membar #Sync ;\ 8810Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8820Sstevel@tonic-gate or %g0, P_UTRAP4, %g2 ;\ 8830Sstevel@tonic-gate or %g0, T_UNIMP_INSTR, %g3 ;\ 8840Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 8850Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 8860Sstevel@tonic-gate nop ;\ 8870Sstevel@tonic-gate .align 32 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate/* 8900Sstevel@tonic-gate * tag overflow trap 8910Sstevel@tonic-gate */ 8920Sstevel@tonic-gate#define TAG_OVERFLOW \ 8930Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 8940Sstevel@tonic-gate or %g0, P_UTRAP10, %g2 ;\ 8950Sstevel@tonic-gate or %g0, T_TAG_OVERFLOW, %g3 ;\ 8960Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 8970Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 8980Sstevel@tonic-gate nop ;\ 8990Sstevel@tonic-gate .align 32 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate/* 9020Sstevel@tonic-gate * divide by zero trap 9030Sstevel@tonic-gate */ 9040Sstevel@tonic-gate#define DIV_BY_ZERO \ 9050Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 9060Sstevel@tonic-gate or %g0, P_UTRAP11, %g2 ;\ 9070Sstevel@tonic-gate or %g0, T_IDIV0, %g3 ;\ 9080Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 9090Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 9100Sstevel@tonic-gate nop ;\ 9110Sstevel@tonic-gate .align 32 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate/* 9140Sstevel@tonic-gate * trap instruction for V9 user trap handlers 9150Sstevel@tonic-gate */ 9160Sstevel@tonic-gate#define TRAP_INSTR \ 9170Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 9180Sstevel@tonic-gate or %g0, T_SOFTWARE_TRAP, %g3 ;\ 9190Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 9200Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 9210Sstevel@tonic-gate nop ;\ 9220Sstevel@tonic-gate .align 32 9230Sstevel@tonic-gate#define TRP4 TRAP_INSTR; TRAP_INSTR; TRAP_INSTR; TRAP_INSTR 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate/* 9260Sstevel@tonic-gate * LEVEL_INTERRUPT is for level N interrupts. 9270Sstevel@tonic-gate * VECTOR_INTERRUPT is for the vector trap. 9280Sstevel@tonic-gate */ 9290Sstevel@tonic-gate#define LEVEL_INTERRUPT(level) \ 9300Sstevel@tonic-gate .global tt_pil/**/level ;\ 9310Sstevel@tonic-gatett_pil/**/level: ;\ 9320Sstevel@tonic-gate ba,pt %xcc, pil_interrupt ;\ 9330Sstevel@tonic-gate mov level, %g4 ;\ 9340Sstevel@tonic-gate .align 32 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate#define LEVEL14_INTERRUPT \ 9370Sstevel@tonic-gate ba pil14_interrupt ;\ 9380Sstevel@tonic-gate mov PIL_14, %g4 ;\ 9390Sstevel@tonic-gate .align 32 9400Sstevel@tonic-gate 9418803SJonathan.Haslam@Sun.COM#define LEVEL15_INTERRUPT \ 9428803SJonathan.Haslam@Sun.COM ba pil15_interrupt ;\ 9438803SJonathan.Haslam@Sun.COM mov PIL_15, %g4 ;\ 9448803SJonathan.Haslam@Sun.COM .align 32 9458803SJonathan.Haslam@Sun.COM 9460Sstevel@tonic-gate#define VECTOR_INTERRUPT \ 9470Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g1 ;\ 9480Sstevel@tonic-gate btst IRSR_BUSY, %g1 ;\ 9490Sstevel@tonic-gate bnz,pt %xcc, vec_interrupt ;\ 9500Sstevel@tonic-gate nop ;\ 9510Sstevel@tonic-gate ba,a,pt %xcc, vec_intr_spurious ;\ 9520Sstevel@tonic-gate .empty ;\ 9530Sstevel@tonic-gate .align 32 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate/* 9560Sstevel@tonic-gate * MMU Trap Handlers. 9570Sstevel@tonic-gate */ 9580Sstevel@tonic-gate#define SWITCH_GLOBALS /* mmu->alt, alt->mmu */ \ 9590Sstevel@tonic-gate rdpr %pstate, %g5 ;\ 9600Sstevel@tonic-gate wrpr %g5, PSTATE_MG | PSTATE_AG, %pstate 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate#define IMMU_EXCEPTION \ 9630Sstevel@tonic-gate membar #Sync ;\ 9640Sstevel@tonic-gate SWITCH_GLOBALS ;\ 9650Sstevel@tonic-gate wr %g0, ASI_IMMU, %asi ;\ 9660Sstevel@tonic-gate rdpr %tpc, %g2 ;\ 9670Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9680Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end ;\ 9690Sstevel@tonic-gate mov T_INSTR_EXCEPTION, %g1 ;\ 9700Sstevel@tonic-gate .align 32 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate#define DMMU_EXCEPTION \ 9730Sstevel@tonic-gate SWITCH_GLOBALS ;\ 9740Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 9750Sstevel@tonic-gate ldxa [MMU_TAG_ACCESS]%asi, %g2 ;\ 9760Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9770Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end ;\ 9780Sstevel@tonic-gate mov T_DATA_EXCEPTION, %g1 ;\ 9790Sstevel@tonic-gate .align 32 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate#define DMMU_EXC_AG_PRIV \ 9820Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 9830Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 9840Sstevel@tonic-gate ba,pt %xcc, .mmu_priv_exception ;\ 9850Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9860Sstevel@tonic-gate .align 32 9870Sstevel@tonic-gate 9880Sstevel@tonic-gate#define DMMU_EXC_AG_NOT_ALIGNED \ 9890Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 9900Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 9910Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 9920Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 9930Sstevel@tonic-gate .align 32 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate/* 9960Sstevel@tonic-gate * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2) 9970Sstevel@tonic-gate */ 9980Sstevel@tonic-gate#define DMMU_EXC_LDDF_NOT_ALIGNED \ 9990Sstevel@tonic-gate btst 1, %sp ;\ 10000Sstevel@tonic-gate bnz,pt %xcc, .lddf_exception_not_aligned ;\ 10010Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 10020Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 10030Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 10040Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 10050Sstevel@tonic-gate .align 32 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate#define DMMU_EXC_STDF_NOT_ALIGNED \ 10080Sstevel@tonic-gate btst 1, %sp ;\ 10090Sstevel@tonic-gate bnz,pt %xcc, .stdf_exception_not_aligned ;\ 10100Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi ;\ 10110Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g2 ;\ 10120Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 10130Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g3 ;\ 10140Sstevel@tonic-gate .align 32 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate/* 10170Sstevel@tonic-gate * Flush the TLB using either the primary, secondary, or nucleus flush 10180Sstevel@tonic-gate * operation based on whether the ctx from the tag access register matches 10190Sstevel@tonic-gate * the primary or secondary context (flush the nucleus if neither matches). 10200Sstevel@tonic-gate * 10210Sstevel@tonic-gate * Requires a membar #Sync before next ld/st. 10220Sstevel@tonic-gate * exits with: 10230Sstevel@tonic-gate * g2 = tag access register 10240Sstevel@tonic-gate * g3 = ctx number 10250Sstevel@tonic-gate */ 10260Sstevel@tonic-gate#if TAGACC_CTX_MASK != CTXREG_CTX_MASK 10270Sstevel@tonic-gate#error "TAGACC_CTX_MASK != CTXREG_CTX_MASK" 10280Sstevel@tonic-gate#endif 10290Sstevel@tonic-gate#define DTLB_DEMAP_ENTRY \ 10300Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g1 ;\ 10310Sstevel@tonic-gate mov MMU_PCONTEXT, %g5 ;\ 10320Sstevel@tonic-gate ldxa [%g1]ASI_DMMU, %g2 ;\ 10330Sstevel@tonic-gate sethi %hi(TAGACC_CTX_MASK), %g4 ;\ 10340Sstevel@tonic-gate or %g4, %lo(TAGACC_CTX_MASK), %g4 ;\ 10350Sstevel@tonic-gate and %g2, %g4, %g3 /* g3 = ctx */ ;\ 10360Sstevel@tonic-gate ldxa [%g5]ASI_DMMU, %g6 /* g6 = primary ctx */ ;\ 10370Sstevel@tonic-gate and %g6, %g4, %g6 /* &= CTXREG_CTX_MASK */ ;\ 10380Sstevel@tonic-gate cmp %g3, %g6 ;\ 10390Sstevel@tonic-gate be,pt %xcc, 1f ;\ 10400Sstevel@tonic-gate andn %g2, %g4, %g1 /* ctx = primary */ ;\ 10410Sstevel@tonic-gate mov MMU_SCONTEXT, %g5 ;\ 10420Sstevel@tonic-gate ldxa [%g5]ASI_DMMU, %g6 /* g6 = secondary ctx */ ;\ 10430Sstevel@tonic-gate and %g6, %g4, %g6 /* &= CTXREG_CTX_MASK */ ;\ 10440Sstevel@tonic-gate cmp %g3, %g6 ;\ 10450Sstevel@tonic-gate be,a,pt %xcc, 1f ;\ 10460Sstevel@tonic-gate or %g1, DEMAP_SECOND, %g1 ;\ 10470Sstevel@tonic-gate or %g1, DEMAP_NUCLEUS, %g1 ;\ 10480Sstevel@tonic-gate1: stxa %g0, [%g1]ASI_DTLB_DEMAP /* MMU_DEMAP_PAGE */ ;\ 10490Sstevel@tonic-gate membar #Sync 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate#if defined(cscope) 10520Sstevel@tonic-gate/* 10530Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that 10540Sstevel@tonic-gate * are generated by macro expansion of DTLB_MISS(). 10550Sstevel@tonic-gate */ 10560Sstevel@tonic-gate .global tt0_dtlbmiss 10570Sstevel@tonic-gatett0_dtlbmiss: 10580Sstevel@tonic-gate .global tt1_dtlbmiss 10590Sstevel@tonic-gatett1_dtlbmiss: 10600Sstevel@tonic-gate nop 10610Sstevel@tonic-gate#endif 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate/* 10640Sstevel@tonic-gate * Needs to be exactly 32 instructions 10650Sstevel@tonic-gate * 10660Sstevel@tonic-gate * UTLB NOTE: If we don't hit on the 8k pointer then we branch 10670Sstevel@tonic-gate * to a special 4M tsb handler. It would be nice if that handler 10680Sstevel@tonic-gate * could live in this file but currently it seems better to allow 10690Sstevel@tonic-gate * it to fall thru to sfmmu_tsb_miss. 10700Sstevel@tonic-gate */ 10711772Sjl139090#ifdef UTSB_PHYS 10721772Sjl139090#define DTLB_MISS(table_name) ;\ 10731772Sjl139090 .global table_name/**/_dtlbmiss ;\ 10741772Sjl139090table_name/**/_dtlbmiss: ;\ 10751772Sjl139090 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 10761772Sjl139090 ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 10771772Sjl139090 ldxa [%g6]ASI_DMMU, %g2 /* g2 = tag access */ ;\ 10781772Sjl139090 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 10791772Sjl139090 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 10801772Sjl139090 cmp %g3, INVALID_CONTEXT ;\ 10811772Sjl139090 ble,pn %xcc, sfmmu_kdtlb_miss ;\ 10826127Ssm142603 srax %g2, PREDISM_BASESHIFT, %g6 /* g6 > 0 ISM predicted */ ;\ 10836127Ssm142603 brgz,pn %g6, sfmmu_udtlb_slowpath_ismpred ;\ 10841772Sjl139090 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 10851772Sjl139090 ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, %g5 data */;\ 10861772Sjl139090 cmp %g4, %g7 ;\ 10876127Ssm142603 bne,pn %xcc, sfmmu_udtlb_slowpath_noismpred ;\ 10886127Ssm142603 nop ;\ 10891772Sjl139090 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 10901772Sjl139090 stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\ 10911772Sjl139090 retry /* in %g5 */ ;\ 10921772Sjl139090 unimp 0 ;\ 10931772Sjl139090 unimp 0 ;\ 10941772Sjl139090 unimp 0 ;\ 10951772Sjl139090 unimp 0 ;\ 10961772Sjl139090 unimp 0 ;\ 10971772Sjl139090 unimp 0 ;\ 10981772Sjl139090 unimp 0 ;\ 10991772Sjl139090 unimp 0 ;\ 11001772Sjl139090 unimp 0 ;\ 11016127Ssm142603 unimp 0 ;\ 11026127Ssm142603 unimp 0 ;\ 11036127Ssm142603 unimp 0 ;\ 11046127Ssm142603 unimp 0 ;\ 11056127Ssm142603 unimp 0 ;\ 11061772Sjl139090 .align 128 11076127Ssm142603 11081772Sjl139090#else /* UTSB_PHYS */ 11090Sstevel@tonic-gate#define DTLB_MISS(table_name) ;\ 11100Sstevel@tonic-gate .global table_name/**/_dtlbmiss ;\ 11110Sstevel@tonic-gatetable_name/**/_dtlbmiss: ;\ 11120Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 11130Sstevel@tonic-gate ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 11140Sstevel@tonic-gate ldxa [%g6]ASI_DMMU, %g2 /* g2 = tag access */ ;\ 11150Sstevel@tonic-gate sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 11160Sstevel@tonic-gate srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 11170Sstevel@tonic-gate cmp %g3, INVALID_CONTEXT ;\ 11180Sstevel@tonic-gate ble,pn %xcc, sfmmu_kdtlb_miss ;\ 11190Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 11200Sstevel@tonic-gate brlz,pn %g1, sfmmu_udtlb_slowpath ;\ 11210Sstevel@tonic-gate nop ;\ 11220Sstevel@tonic-gate ldda [%g1]ASI_NQUAD_LD, %g4 /* g4 = tag, %g5 data */ ;\ 11230Sstevel@tonic-gate cmp %g4, %g7 ;\ 11240Sstevel@tonic-gate bne,pn %xcc, sfmmu_tsb_miss_tt /* no 4M TSB, miss */ ;\ 11254528Spaulsan mov -1, %g3 /* set 4M tsbe ptr to -1 */ ;\ 11260Sstevel@tonic-gate TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 11270Sstevel@tonic-gate stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\ 11280Sstevel@tonic-gate retry /* in %g5 */ ;\ 11290Sstevel@tonic-gate unimp 0 ;\ 11300Sstevel@tonic-gate unimp 0 ;\ 11310Sstevel@tonic-gate unimp 0 ;\ 11320Sstevel@tonic-gate unimp 0 ;\ 11330Sstevel@tonic-gate unimp 0 ;\ 11344528Spaulsan unimp 0 ;\ 11354528Spaulsan unimp 0 ;\ 11364528Spaulsan unimp 0 ;\ 11374528Spaulsan unimp 0 ;\ 11384528Spaulsan unimp 0 ;\ 11394528Spaulsan unimp 0 ;\ 11404528Spaulsan unimp 0 ;\ 11414528Spaulsan unimp 0 ;\ 11424528Spaulsan unimp 0 ;\ 11430Sstevel@tonic-gate .align 128 11441772Sjl139090#endif /* UTSB_PHYS */ 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate#if defined(cscope) 11470Sstevel@tonic-gate/* 11480Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that 11490Sstevel@tonic-gate * are generated by macro expansion of ITLB_MISS(). 11500Sstevel@tonic-gate */ 11510Sstevel@tonic-gate .global tt0_itlbmiss 11520Sstevel@tonic-gatett0_itlbmiss: 11530Sstevel@tonic-gate .global tt1_itlbmiss 11540Sstevel@tonic-gatett1_itlbmiss: 11550Sstevel@tonic-gate nop 11560Sstevel@tonic-gate#endif 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate/* 11590Sstevel@tonic-gate * Instruction miss handler. 11600Sstevel@tonic-gate * ldda instructions will have their ASI patched 11610Sstevel@tonic-gate * by sfmmu_patch_ktsb at runtime. 11620Sstevel@tonic-gate * MUST be EXACTLY 32 instructions or we'll break. 11630Sstevel@tonic-gate */ 11641772Sjl139090#ifdef UTSB_PHYS 11656127Ssm142603#define ITLB_MISS(table_name) \ 11666127Ssm142603 .global table_name/**/_itlbmiss ;\ 11676127Ssm142603table_name/**/_itlbmiss: ;\ 11686127Ssm142603 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 11696127Ssm142603 ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 11706127Ssm142603 ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\ 11716127Ssm142603 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 11726127Ssm142603 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 11736127Ssm142603 cmp %g3, INVALID_CONTEXT ;\ 11746127Ssm142603 ble,pn %xcc, sfmmu_kitlb_miss ;\ 11756127Ssm142603 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 11766127Ssm142603 ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ 11776127Ssm142603 cmp %g4, %g7 ;\ 11786127Ssm142603 bne,pn %xcc, sfmmu_uitlb_slowpath ;\ 11796127Ssm142603 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 11806127Ssm142603 bz,pn %icc, exec_fault ;\ 11816127Ssm142603 nop ;\ 11826127Ssm142603 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 11836127Ssm142603 stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\ 11846127Ssm142603 retry ;\ 11854528Spaulsan unimp 0 ;\ 11864528Spaulsan unimp 0 ;\ 11874528Spaulsan unimp 0 ;\ 11886127Ssm142603 unimp 0 ;\ 11896127Ssm142603 unimp 0 ;\ 11906127Ssm142603 unimp 0 ;\ 11916127Ssm142603 unimp 0 ;\ 11926127Ssm142603 unimp 0 ;\ 11936127Ssm142603 unimp 0 ;\ 11946127Ssm142603 unimp 0 ;\ 11956127Ssm142603 unimp 0 ;\ 11966127Ssm142603 unimp 0 ;\ 11976127Ssm142603 unimp 0 ;\ 11986127Ssm142603 unimp 0 ;\ 11996127Ssm142603 .align 128 12006127Ssm142603 12011772Sjl139090#else /* UTSB_PHYS */ 12020Sstevel@tonic-gate#define ITLB_MISS(table_name) \ 12030Sstevel@tonic-gate .global table_name/**/_itlbmiss ;\ 12040Sstevel@tonic-gatetable_name/**/_itlbmiss: ;\ 12050Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ 12060Sstevel@tonic-gate ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 12070Sstevel@tonic-gate ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\ 12080Sstevel@tonic-gate sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ 12090Sstevel@tonic-gate srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ 12100Sstevel@tonic-gate cmp %g3, INVALID_CONTEXT ;\ 12110Sstevel@tonic-gate ble,pn %xcc, sfmmu_kitlb_miss ;\ 12120Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 12130Sstevel@tonic-gate brlz,pn %g1, sfmmu_uitlb_slowpath /* if >1 TSB branch */ ;\ 12140Sstevel@tonic-gate nop ;\ 12150Sstevel@tonic-gate ldda [%g1]ASI_NQUAD_LD, %g4 /* g4 = tag, g5 = data */ ;\ 12160Sstevel@tonic-gate cmp %g4, %g7 ;\ 12170Sstevel@tonic-gate bne,pn %xcc, sfmmu_tsb_miss_tt /* br if 8k ptr miss */ ;\ 12184528Spaulsan mov -1, %g3 /* set 4M TSB ptr to -1 */ ;\ 12190Sstevel@tonic-gate andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 12200Sstevel@tonic-gate bz,pn %icc, exec_fault ;\ 12210Sstevel@tonic-gate nop ;\ 12220Sstevel@tonic-gate TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ 12230Sstevel@tonic-gate stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\ 12240Sstevel@tonic-gate retry ;\ 12250Sstevel@tonic-gate unimp 0 ;\ 12260Sstevel@tonic-gate unimp 0 ;\ 12270Sstevel@tonic-gate unimp 0 ;\ 12280Sstevel@tonic-gate unimp 0 ;\ 12290Sstevel@tonic-gate unimp 0 ;\ 12304528Spaulsan unimp 0 ;\ 12314528Spaulsan unimp 0 ;\ 12324528Spaulsan unimp 0 ;\ 12334528Spaulsan unimp 0 ;\ 12344528Spaulsan unimp 0 ;\ 12354528Spaulsan unimp 0 ;\ 12360Sstevel@tonic-gate .align 128 12371772Sjl139090#endif /* UTSB_PHYS */ 12380Sstevel@tonic-gate 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate/* 12410Sstevel@tonic-gate * This macro is the first level handler for fast protection faults. 12420Sstevel@tonic-gate * It first demaps the tlb entry which generated the fault and then 12430Sstevel@tonic-gate * attempts to set the modify bit on the hash. It needs to be 12440Sstevel@tonic-gate * exactly 32 instructions. 12450Sstevel@tonic-gate */ 12460Sstevel@tonic-gate#define DTLB_PROT \ 12470Sstevel@tonic-gate DTLB_DEMAP_ENTRY /* 20 instructions */ ;\ 12480Sstevel@tonic-gate /* ;\ 12490Sstevel@tonic-gate * At this point: ;\ 12500Sstevel@tonic-gate * g1 = ???? ;\ 12510Sstevel@tonic-gate * g2 = tag access register ;\ 12520Sstevel@tonic-gate * g3 = ctx number ;\ 12530Sstevel@tonic-gate * g4 = ???? ;\ 12540Sstevel@tonic-gate */ ;\ 12550Sstevel@tonic-gate TT_TRACE(trace_dataprot) /* 2 instr ifdef TRAPTRACE */ ;\ 12560Sstevel@tonic-gate /* clobbers g1 and g6 */ ;\ 12570Sstevel@tonic-gate ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ 12580Sstevel@tonic-gate brnz,pt %g3, sfmmu_uprot_trap /* user trap */ ;\ 12590Sstevel@tonic-gate nop ;\ 12600Sstevel@tonic-gate ba,a,pt %xcc, sfmmu_kprot_trap /* kernel trap */ ;\ 12610Sstevel@tonic-gate unimp 0 ;\ 12620Sstevel@tonic-gate unimp 0 ;\ 12630Sstevel@tonic-gate unimp 0 ;\ 12640Sstevel@tonic-gate unimp 0 ;\ 12650Sstevel@tonic-gate unimp 0 ;\ 12660Sstevel@tonic-gate unimp 0 ;\ 12670Sstevel@tonic-gate .align 128 12680Sstevel@tonic-gate 12690Sstevel@tonic-gate#define DMMU_EXCEPTION_TL1 ;\ 12700Sstevel@tonic-gate SWITCH_GLOBALS ;\ 12710Sstevel@tonic-gate ba,a,pt %xcc, mmu_trap_tl1 ;\ 12720Sstevel@tonic-gate nop ;\ 12730Sstevel@tonic-gate .align 32 12740Sstevel@tonic-gate 12750Sstevel@tonic-gate#define MISALIGN_ADDR_TL1 ;\ 12760Sstevel@tonic-gate ba,a,pt %xcc, mmu_trap_tl1 ;\ 12770Sstevel@tonic-gate nop ;\ 12780Sstevel@tonic-gate .align 32 12790Sstevel@tonic-gate 12800Sstevel@tonic-gate/* 12810Sstevel@tonic-gate * Trace a tsb hit 12820Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 12830Sstevel@tonic-gate * g2 = tag access register (in) 12840Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 12850Sstevel@tonic-gate * g5 = tsbe data (in) 12860Sstevel@tonic-gate * g6 = scratch (clobbered) 12870Sstevel@tonic-gate * g7 = pc we jumped here from (in) 12880Sstevel@tonic-gate * ttextra = value to OR in to trap type (%tt) (in) 12890Sstevel@tonic-gate */ 12900Sstevel@tonic-gate#ifdef TRAPTRACE 12910Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra) \ 12920Sstevel@tonic-gate membar #Sync ;\ 12930Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 ;\ 12940Sstevel@tonic-gate flush %g6 ;\ 12950Sstevel@tonic-gate TRACE_PTR(%g3, %g6) ;\ 1296*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) ;\ 12970Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi ;\ 12980Sstevel@tonic-gate stxa %g2, [%g3 + TRAP_ENT_SP]%asi /* tag access */ ;\ 12990Sstevel@tonic-gate stxa %g5, [%g3 + TRAP_ENT_F1]%asi /* tsb data */ ;\ 13000Sstevel@tonic-gate rdpr %tnpc, %g6 ;\ 13010Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_F2]%asi ;\ 13020Sstevel@tonic-gate stxa %g1, [%g3 + TRAP_ENT_F3]%asi /* tsb pointer */ ;\ 13030Sstevel@tonic-gate stxa %g0, [%g3 + TRAP_ENT_F4]%asi ;\ 13040Sstevel@tonic-gate rdpr %tpc, %g6 ;\ 13050Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TPC]%asi ;\ 13060Sstevel@tonic-gate rdpr %tl, %g6 ;\ 13070Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TL]%asi ;\ 13080Sstevel@tonic-gate rdpr %tt, %g6 ;\ 13090Sstevel@tonic-gate or %g6, (ttextra), %g6 ;\ 13100Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi ;\ 13110Sstevel@tonic-gate ldxa [%g0]ASI_IMMU, %g1 /* tag target */ ;\ 13120Sstevel@tonic-gate ldxa [%g0]ASI_DMMU, %g4 ;\ 13130Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT ;\ 13140Sstevel@tonic-gate movne %icc, %g4, %g1 ;\ 13150Sstevel@tonic-gate stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tsb tag */ ;\ 13160Sstevel@tonic-gate stxa %g0, [%g3 + TRAP_ENT_TR]%asi ;\ 13170Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g6) 13180Sstevel@tonic-gate#else 13190Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra) 13200Sstevel@tonic-gate#endif 13210Sstevel@tonic-gate 13220Sstevel@tonic-gate#if defined(lint) 13230Sstevel@tonic-gate 13240Sstevel@tonic-gatestruct scb trap_table; 13250Sstevel@tonic-gatestruct scb scb; /* trap_table/scb are the same object */ 13260Sstevel@tonic-gate 13270Sstevel@tonic-gate#else /* lint */ 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate/* 13300Sstevel@tonic-gate * ======================================================================= 13310Sstevel@tonic-gate * SPARC V9 TRAP TABLE 13320Sstevel@tonic-gate * 13330Sstevel@tonic-gate * The trap table is divided into two halves: the first half is used when 13340Sstevel@tonic-gate * taking traps when TL=0; the second half is used when taking traps from 13350Sstevel@tonic-gate * TL>0. Note that handlers in the second half of the table might not be able 13360Sstevel@tonic-gate * to make the same assumptions as handlers in the first half of the table. 13370Sstevel@tonic-gate * 13380Sstevel@tonic-gate * Worst case trap nesting so far: 13390Sstevel@tonic-gate * 13400Sstevel@tonic-gate * at TL=0 client issues software trap requesting service 13410Sstevel@tonic-gate * at TL=1 nucleus wants a register window 13420Sstevel@tonic-gate * at TL=2 register window clean/spill/fill takes a TLB miss 13430Sstevel@tonic-gate * at TL=3 processing TLB miss 13440Sstevel@tonic-gate * at TL=4 handle asynchronous error 13450Sstevel@tonic-gate * 13460Sstevel@tonic-gate * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode". 13470Sstevel@tonic-gate * 13480Sstevel@tonic-gate * ======================================================================= 13490Sstevel@tonic-gate */ 13500Sstevel@tonic-gate .section ".text" 13510Sstevel@tonic-gate .align 4 13520Sstevel@tonic-gate .global trap_table, scb, trap_table0, trap_table1, etrap_table 13531640Spetede .type trap_table, #object 13541640Spetede .type scb, #object 13550Sstevel@tonic-gatetrap_table: 13560Sstevel@tonic-gatescb: 13570Sstevel@tonic-gatetrap_table0: 13580Sstevel@tonic-gate /* hardware traps */ 13590Sstevel@tonic-gate NOT; /* 000 reserved */ 13600Sstevel@tonic-gate RED; /* 001 power on reset */ 13610Sstevel@tonic-gate RED; /* 002 watchdog reset */ 13620Sstevel@tonic-gate RED; /* 003 externally initiated reset */ 13630Sstevel@tonic-gate RED; /* 004 software initiated reset */ 13640Sstevel@tonic-gate RED; /* 005 red mode exception */ 13650Sstevel@tonic-gate NOT; NOT; /* 006 - 007 reserved */ 13660Sstevel@tonic-gate IMMU_EXCEPTION; /* 008 instruction access exception */ 13670Sstevel@tonic-gate NOT; /* 009 instruction access MMU miss */ 13681772Sjl139090 ASYNC_TRAP(T_INSTR_ERROR, trace_gen, tt0_iae); 13690Sstevel@tonic-gate /* 00A instruction access error */ 13700Sstevel@tonic-gate NOT; NOT4; /* 00B - 00F reserved */ 13710Sstevel@tonic-gate ILLTRAP_INSTR; /* 010 illegal instruction */ 13720Sstevel@tonic-gate TRAP(T_PRIV_INSTR); /* 011 privileged opcode */ 13730Sstevel@tonic-gate NOT; /* 012 unimplemented LDD */ 13740Sstevel@tonic-gate NOT; /* 013 unimplemented STD */ 13750Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 014 - 01F reserved */ 13760Sstevel@tonic-gate FP_DISABLED_TRAP; /* 020 fp disabled */ 13770Sstevel@tonic-gate FP_IEEE_TRAP; /* 021 fp exception ieee 754 */ 13780Sstevel@tonic-gate FP_TRAP; /* 022 fp exception other */ 13790Sstevel@tonic-gate TAG_OVERFLOW; /* 023 tag overflow */ 13800Sstevel@tonic-gate CLEAN_WINDOW; /* 024 - 027 clean window */ 13810Sstevel@tonic-gate DIV_BY_ZERO; /* 028 division by zero */ 13820Sstevel@tonic-gate NOT; /* 029 internal processor error */ 13830Sstevel@tonic-gate NOT; NOT; NOT4; /* 02A - 02F reserved */ 13840Sstevel@tonic-gate DMMU_EXCEPTION; /* 030 data access exception */ 13850Sstevel@tonic-gate NOT; /* 031 data access MMU miss */ 13861772Sjl139090 ASYNC_TRAP(T_DATA_ERROR, trace_gen, tt0_dae); 13870Sstevel@tonic-gate /* 032 data access error */ 13880Sstevel@tonic-gate NOT; /* 033 data access protection */ 13890Sstevel@tonic-gate DMMU_EXC_AG_NOT_ALIGNED; /* 034 mem address not aligned */ 13900Sstevel@tonic-gate DMMU_EXC_LDDF_NOT_ALIGNED; /* 035 LDDF mem address not aligned */ 13910Sstevel@tonic-gate DMMU_EXC_STDF_NOT_ALIGNED; /* 036 STDF mem address not aligned */ 13920Sstevel@tonic-gate DMMU_EXC_AG_PRIV; /* 037 privileged action */ 13930Sstevel@tonic-gate NOT; /* 038 LDQF mem address not aligned */ 13940Sstevel@tonic-gate NOT; /* 039 STQF mem address not aligned */ 13950Sstevel@tonic-gate NOT; NOT; NOT4; /* 03A - 03F reserved */ 13961772Sjl139090 LABELED_BAD(tt0_asdat); /* 040 async data error */ 13970Sstevel@tonic-gate LEVEL_INTERRUPT(1); /* 041 interrupt level 1 */ 13980Sstevel@tonic-gate LEVEL_INTERRUPT(2); /* 042 interrupt level 2 */ 13990Sstevel@tonic-gate LEVEL_INTERRUPT(3); /* 043 interrupt level 3 */ 14000Sstevel@tonic-gate LEVEL_INTERRUPT(4); /* 044 interrupt level 4 */ 14010Sstevel@tonic-gate LEVEL_INTERRUPT(5); /* 045 interrupt level 5 */ 14020Sstevel@tonic-gate LEVEL_INTERRUPT(6); /* 046 interrupt level 6 */ 14030Sstevel@tonic-gate LEVEL_INTERRUPT(7); /* 047 interrupt level 7 */ 14040Sstevel@tonic-gate LEVEL_INTERRUPT(8); /* 048 interrupt level 8 */ 14050Sstevel@tonic-gate LEVEL_INTERRUPT(9); /* 049 interrupt level 9 */ 14060Sstevel@tonic-gate LEVEL_INTERRUPT(10); /* 04A interrupt level 10 */ 14070Sstevel@tonic-gate LEVEL_INTERRUPT(11); /* 04B interrupt level 11 */ 14080Sstevel@tonic-gate LEVEL_INTERRUPT(12); /* 04C interrupt level 12 */ 14090Sstevel@tonic-gate LEVEL_INTERRUPT(13); /* 04D interrupt level 13 */ 14100Sstevel@tonic-gate LEVEL14_INTERRUPT; /* 04E interrupt level 14 */ 14118803SJonathan.Haslam@Sun.COM LEVEL15_INTERRUPT; /* 04F interrupt level 15 */ 14120Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 050 - 05F reserved */ 14130Sstevel@tonic-gate VECTOR_INTERRUPT; /* 060 interrupt vector */ 14140Sstevel@tonic-gate GOTO(kmdb_trap); /* 061 PA watchpoint */ 14150Sstevel@tonic-gate GOTO(kmdb_trap); /* 062 VA watchpoint */ 14160Sstevel@tonic-gate GOTO_TT(ce_err, trace_gen); /* 063 corrected ECC error */ 14170Sstevel@tonic-gate ITLB_MISS(tt0); /* 064 instruction access MMU miss */ 14180Sstevel@tonic-gate DTLB_MISS(tt0); /* 068 data access MMU miss */ 14190Sstevel@tonic-gate DTLB_PROT; /* 06C data access protection */ 14200Sstevel@tonic-gate LABELED_BAD(tt0_fecc); /* 070 fast ecache ECC error */ 14210Sstevel@tonic-gate LABELED_BAD(tt0_dperr); /* 071 Cheetah+ dcache parity error */ 14220Sstevel@tonic-gate LABELED_BAD(tt0_iperr); /* 072 Cheetah+ icache parity error */ 14230Sstevel@tonic-gate NOT; /* 073 reserved */ 14240Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 074 - 07F reserved */ 14250Sstevel@tonic-gate NOT4; /* 080 spill 0 normal */ 14260Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUP,sn0); /* 084 spill 1 normal */ 14270Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUP,sn0); /* 088 spill 2 normal */ 14280Sstevel@tonic-gate SPILL_32clean(ASI_AIUP,sn0); /* 08C spill 3 normal */ 14290Sstevel@tonic-gate SPILL_64clean(ASI_AIUP,sn0); /* 090 spill 4 normal */ 14300Sstevel@tonic-gate SPILL_32bit(not); /* 094 spill 5 normal */ 14310Sstevel@tonic-gate SPILL_64bit(not); /* 098 spill 6 normal */ 14320Sstevel@tonic-gate SPILL_mixed; /* 09C spill 7 normal */ 14330Sstevel@tonic-gate NOT4; /* 0A0 spill 0 other */ 14340Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUS,so0); /* 0A4 spill 1 other */ 14350Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUS,so0); /* 0A8 spill 2 other */ 14360Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUS,so0); /* 0AC spill 3 other */ 14370Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUS,so0); /* 0B0 spill 4 other */ 14380Sstevel@tonic-gate NOT4; /* 0B4 spill 5 other */ 14390Sstevel@tonic-gate NOT4; /* 0B8 spill 6 other */ 14400Sstevel@tonic-gate NOT4; /* 0BC spill 7 other */ 14410Sstevel@tonic-gate NOT4; /* 0C0 fill 0 normal */ 14420Sstevel@tonic-gate FILL_32bit_asi(ASI_AIUP,fn0); /* 0C4 fill 1 normal */ 14430Sstevel@tonic-gate FILL_64bit_asi(ASI_AIUP,fn0); /* 0C8 fill 2 normal */ 14440Sstevel@tonic-gate FILL_32bit_asi(ASI_AIUP,fn0); /* 0CC fill 3 normal */ 14450Sstevel@tonic-gate FILL_64bit_asi(ASI_AIUP,fn0); /* 0D0 fill 4 normal */ 14460Sstevel@tonic-gate FILL_32bit(not); /* 0D4 fill 5 normal */ 14470Sstevel@tonic-gate FILL_64bit(not); /* 0D8 fill 6 normal */ 14480Sstevel@tonic-gate FILL_mixed; /* 0DC fill 7 normal */ 14490Sstevel@tonic-gate NOT4; /* 0E0 fill 0 other */ 14500Sstevel@tonic-gate NOT4; /* 0E4 fill 1 other */ 14510Sstevel@tonic-gate NOT4; /* 0E8 fill 2 other */ 14520Sstevel@tonic-gate NOT4; /* 0EC fill 3 other */ 14530Sstevel@tonic-gate NOT4; /* 0F0 fill 4 other */ 14540Sstevel@tonic-gate NOT4; /* 0F4 fill 5 other */ 14550Sstevel@tonic-gate NOT4; /* 0F8 fill 6 other */ 14560Sstevel@tonic-gate NOT4; /* 0FC fill 7 other */ 14570Sstevel@tonic-gate /* user traps */ 14580Sstevel@tonic-gate GOTO(syscall_trap_4x); /* 100 old system call */ 14590Sstevel@tonic-gate TRAP(T_BREAKPOINT); /* 101 user breakpoint */ 14600Sstevel@tonic-gate TRAP(T_DIV0); /* 102 user divide by zero */ 14615414Smb158278 FLUSHW(tt0_flushw); /* 103 flush windows */ 14620Sstevel@tonic-gate GOTO(.clean_windows); /* 104 clean windows */ 14630Sstevel@tonic-gate BAD; /* 105 range check ?? */ 14640Sstevel@tonic-gate GOTO(.fix_alignment); /* 106 do unaligned references */ 14650Sstevel@tonic-gate BAD; /* 107 unused */ 14664141Sedp SYSCALL_TRAP32; /* 108 ILP32 system call on LP64 */ 14670Sstevel@tonic-gate GOTO(set_trap0_addr); /* 109 set trap0 address */ 14680Sstevel@tonic-gate BAD; BAD; BAD4; /* 10A - 10F unused */ 14690Sstevel@tonic-gate TRP4; TRP4; TRP4; TRP4; /* 110 - 11F V9 user trap handlers */ 14700Sstevel@tonic-gate GOTO(.getcc); /* 120 get condition codes */ 14710Sstevel@tonic-gate GOTO(.setcc); /* 121 set condition codes */ 14720Sstevel@tonic-gate GOTO(.getpsr); /* 122 get psr */ 14730Sstevel@tonic-gate GOTO(.setpsr); /* 123 set psr (some fields) */ 14740Sstevel@tonic-gate GOTO(get_timestamp); /* 124 get timestamp */ 14750Sstevel@tonic-gate GOTO(get_virtime); /* 125 get lwp virtual time */ 14760Sstevel@tonic-gate PRIV(self_xcall); /* 126 self xcall */ 14770Sstevel@tonic-gate GOTO(get_hrestime); /* 127 get hrestime */ 14780Sstevel@tonic-gate BAD; /* 128 ST_SETV9STACK */ 14790Sstevel@tonic-gate GOTO(.getlgrp); /* 129 get lgrpid */ 14800Sstevel@tonic-gate BAD; BAD; BAD4; /* 12A - 12F unused */ 14810Sstevel@tonic-gate BAD4; BAD4; /* 130 - 137 unused */ 14820Sstevel@tonic-gate DTRACE_PID; /* 138 dtrace pid tracing provider */ 14832179Sahl BAD; /* 139 unused */ 14840Sstevel@tonic-gate DTRACE_RETURN; /* 13A dtrace pid return probe */ 14850Sstevel@tonic-gate BAD; BAD4; /* 13B - 13F unused */ 14864141Sedp SYSCALL_TRAP; /* 140 LP64 system call */ 14871321Srscott SYSCALL(nosys); /* 141 unused system call trap */ 14880Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL 14890Sstevel@tonic-gate GOTO(.traptrace_freeze); /* 142 freeze traptrace */ 14900Sstevel@tonic-gate GOTO(.traptrace_unfreeze); /* 143 unfreeze traptrace */ 14910Sstevel@tonic-gate#else 14921321Srscott SYSCALL(nosys); /* 142 unused system call trap */ 14931321Srscott SYSCALL(nosys); /* 143 unused system call trap */ 14940Sstevel@tonic-gate#endif 14950Sstevel@tonic-gate BAD4; BAD4; BAD4; /* 144 - 14F unused */ 14960Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 150 - 15F unused */ 14970Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 160 - 16F unused */ 14980Sstevel@tonic-gate BAD; /* 170 - unused */ 14990Sstevel@tonic-gate BAD; /* 171 - unused */ 15000Sstevel@tonic-gate BAD; BAD; /* 172 - 173 unused */ 15010Sstevel@tonic-gate BAD4; BAD4; /* 174 - 17B unused */ 15020Sstevel@tonic-gate#ifdef PTL1_PANIC_DEBUG 15030Sstevel@tonic-gate mov PTL1_BAD_DEBUG, %g1; GOTO(ptl1_panic); 15040Sstevel@tonic-gate /* 17C test ptl1_panic */ 15050Sstevel@tonic-gate#else 15060Sstevel@tonic-gate BAD; /* 17C unused */ 15070Sstevel@tonic-gate#endif /* PTL1_PANIC_DEBUG */ 15080Sstevel@tonic-gate PRIV(kmdb_trap); /* 17D kmdb enter (L1-A) */ 15090Sstevel@tonic-gate PRIV(kmdb_trap); /* 17E kmdb breakpoint */ 15100Sstevel@tonic-gate PRIV(kctx_obp_bpt); /* 17F obp breakpoint */ 15110Sstevel@tonic-gate /* reserved */ 15120Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 180 - 18F reserved */ 15130Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 190 - 19F reserved */ 15140Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1A0 - 1AF reserved */ 15150Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1B0 - 1BF reserved */ 15160Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1C0 - 1CF reserved */ 15170Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1D0 - 1DF reserved */ 15180Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1E0 - 1EF reserved */ 15190Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1F0 - 1FF reserved */ 15200Sstevel@tonic-gatetrap_table1: 15210Sstevel@tonic-gate NOT4; NOT4; NOT; NOT; /* 000 - 009 unused */ 15221772Sjl139090 ASYNC_TRAP(T_INSTR_ERROR + T_TL1, trace_gen, tt1_iae); 15230Sstevel@tonic-gate /* 00A instruction access error */ 15240Sstevel@tonic-gate NOT; NOT4; /* 00B - 00F unused */ 15250Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 010 - 01F unused */ 15260Sstevel@tonic-gate NOT4; /* 020 - 023 unused */ 15270Sstevel@tonic-gate CLEAN_WINDOW; /* 024 - 027 clean window */ 15280Sstevel@tonic-gate NOT4; NOT4; /* 028 - 02F unused */ 15290Sstevel@tonic-gate DMMU_EXCEPTION_TL1; /* 030 data access exception */ 15300Sstevel@tonic-gate NOT; /* 031 unused */ 15311772Sjl139090 ASYNC_TRAP(T_DATA_ERROR + T_TL1, trace_gen, tt1_dae); 15320Sstevel@tonic-gate /* 032 data access error */ 15330Sstevel@tonic-gate NOT; /* 033 unused */ 15340Sstevel@tonic-gate MISALIGN_ADDR_TL1; /* 034 mem address not aligned */ 15350Sstevel@tonic-gate NOT; NOT; NOT; NOT4; NOT4 /* 035 - 03F unused */ 15361772Sjl139090 LABELED_BAD(tt1_asdat); /* 040 async data error */ 15371772Sjl139090 NOT; NOT; NOT; /* 041 - 043 unused */ 15381772Sjl139090 NOT4; NOT4; NOT4; /* 044 - 04F unused */ 15390Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 050 - 05F unused */ 15400Sstevel@tonic-gate NOT; /* 060 unused */ 15410Sstevel@tonic-gate GOTO(kmdb_trap_tl1); /* 061 PA watchpoint */ 15420Sstevel@tonic-gate GOTO(kmdb_trap_tl1); /* 062 VA watchpoint */ 15430Sstevel@tonic-gate GOTO_TT(ce_err_tl1, trace_gen); /* 063 corrected ECC error */ 15440Sstevel@tonic-gate ITLB_MISS(tt1); /* 064 instruction access MMU miss */ 15450Sstevel@tonic-gate DTLB_MISS(tt1); /* 068 data access MMU miss */ 15460Sstevel@tonic-gate DTLB_PROT; /* 06C data access protection */ 15470Sstevel@tonic-gate LABELED_BAD(tt1_fecc); /* 070 fast ecache ECC error */ 15480Sstevel@tonic-gate LABELED_BAD(tt1_dperr); /* 071 Cheetah+ dcache parity error */ 15490Sstevel@tonic-gate LABELED_BAD(tt1_iperr); /* 072 Cheetah+ icache parity error */ 15500Sstevel@tonic-gate NOT; /* 073 reserved */ 15510Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 074 - 07F reserved */ 15520Sstevel@tonic-gate NOT4; /* 080 spill 0 normal */ 15530Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUP,sn1); /* 084 spill 1 normal */ 15540Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUP,sn1); /* 088 spill 2 normal */ 15550Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUP,sn1); /* 08C spill 3 normal */ 15560Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUP,sn1); /* 090 spill 4 normal */ 15570Sstevel@tonic-gate SPILL_32bit(not); /* 094 spill 5 normal */ 15580Sstevel@tonic-gate SPILL_64bit(not); /* 098 spill 6 normal */ 15590Sstevel@tonic-gate SPILL_mixed; /* 09C spill 7 normal */ 15600Sstevel@tonic-gate NOT4; /* 0A0 spill 0 other */ 15610Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUS,so1); /* 0A4 spill 1 other */ 15620Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUS,so1); /* 0A8 spill 2 other */ 15630Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUS,so1); /* 0AC spill 3 other */ 15640Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUS,so1); /* 0B0 spill 4 other */ 15650Sstevel@tonic-gate NOT4; /* 0B4 spill 5 other */ 15660Sstevel@tonic-gate NOT4; /* 0B8 spill 6 other */ 15670Sstevel@tonic-gate NOT4; /* 0BC spill 7 other */ 15680Sstevel@tonic-gate NOT4; /* 0C0 fill 0 normal */ 15690Sstevel@tonic-gate FILL_32bit_tt1(ASI_AIUP,fn1); /* 0C4 fill 1 normal */ 15700Sstevel@tonic-gate FILL_64bit_tt1(ASI_AIUP,fn1); /* 0C8 fill 2 normal */ 15710Sstevel@tonic-gate FILL_32bit_tt1(ASI_AIUP,fn1); /* 0CC fill 3 normal */ 15720Sstevel@tonic-gate FILL_64bit_tt1(ASI_AIUP,fn1); /* 0D0 fill 4 normal */ 15730Sstevel@tonic-gate FILL_32bit(not); /* 0D4 fill 5 normal */ 15740Sstevel@tonic-gate FILL_64bit(not); /* 0D8 fill 6 normal */ 15750Sstevel@tonic-gate FILL_mixed; /* 0DC fill 7 normal */ 15760Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 0E0 - 0EF unused */ 15770Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 0F0 - 0FF unused */ 15780Sstevel@tonic-gate LABELED_BAD(tt1_swtrap0); /* 100 fast ecache ECC error (cont) */ 15790Sstevel@tonic-gate LABELED_BAD(tt1_swtrap1); /* 101 Ch+ D$ parity error (cont) */ 15800Sstevel@tonic-gate LABELED_BAD(tt1_swtrap2); /* 102 Ch+ I$ parity error (cont) */ 15810Sstevel@tonic-gate NOT; /* 103 reserved */ 15820Sstevel@tonic-gate/* 15830Sstevel@tonic-gate * We only reserve the above four special case soft traps for code running 15840Sstevel@tonic-gate * at TL>0, so we can truncate the trap table here. 15850Sstevel@tonic-gate */ 15860Sstevel@tonic-gateetrap_table: 15870Sstevel@tonic-gate .size trap_table, (.-trap_table) 15880Sstevel@tonic-gate .size scb, (.-scb) 15890Sstevel@tonic-gate 15900Sstevel@tonic-gate/* 15910Sstevel@tonic-gate * We get to exec_fault in the case of an instruction miss and tte 15920Sstevel@tonic-gate * has no execute bit set. We go to tl0 to handle it. 15930Sstevel@tonic-gate * 15940Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 15950Sstevel@tonic-gate * g2 = tag access register (in) 15960Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 15970Sstevel@tonic-gate * g5 = tsbe data (in) 15980Sstevel@tonic-gate * g6 = scratch (clobbered) 15990Sstevel@tonic-gate */ 16000Sstevel@tonic-gate ALTENTRY(exec_fault) 16010Sstevel@tonic-gate TRACE_TSBHIT(0x200) 16020Sstevel@tonic-gate SWITCH_GLOBALS 16030Sstevel@tonic-gate mov MMU_TAG_ACCESS, %g4 16040Sstevel@tonic-gate ldxa [%g4]ASI_IMMU, %g2 ! arg1 = addr 16050Sstevel@tonic-gate mov T_INSTR_MMU_MISS, %g3 ! arg2 = traptype 16060Sstevel@tonic-gate set trap, %g1 16070Sstevel@tonic-gate ba,pt %xcc, sys_trap 16080Sstevel@tonic-gate mov -1, %g4 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate.mmu_exception_not_aligned: 16110Sstevel@tonic-gate rdpr %tstate, %g1 16120Sstevel@tonic-gate btst TSTATE_PRIV, %g1 16130Sstevel@tonic-gate bnz,pn %icc, 2f 16140Sstevel@tonic-gate nop 16150Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16160Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16170Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 16180Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 16190Sstevel@tonic-gate brz,pt %g5, 2f 16200Sstevel@tonic-gate nop 16210Sstevel@tonic-gate ldn [%g5 + P_UTRAP15], %g5 ! unaligned utrap? 16220Sstevel@tonic-gate brz,pn %g5, 2f 16230Sstevel@tonic-gate nop 16240Sstevel@tonic-gate btst 1, %sp 16250Sstevel@tonic-gate bz,pt %xcc, 1f ! 32 bit user program 16260Sstevel@tonic-gate nop 16270Sstevel@tonic-gate ba,pt %xcc, .setup_v9utrap ! 64 bit user program 16280Sstevel@tonic-gate nop 16290Sstevel@tonic-gate1: 16300Sstevel@tonic-gate ba,pt %xcc, .setup_utrap 16310Sstevel@tonic-gate or %g2, %g0, %g7 16320Sstevel@tonic-gate2: 16330Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end 16340Sstevel@tonic-gate mov T_ALIGNMENT, %g1 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate.mmu_priv_exception: 16370Sstevel@tonic-gate rdpr %tstate, %g1 16380Sstevel@tonic-gate btst TSTATE_PRIV, %g1 16390Sstevel@tonic-gate bnz,pn %icc, 1f 16400Sstevel@tonic-gate nop 16410Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16420Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16430Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 16440Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 16450Sstevel@tonic-gate brz,pt %g5, 1f 16460Sstevel@tonic-gate nop 16470Sstevel@tonic-gate ldn [%g5 + P_UTRAP16], %g5 16480Sstevel@tonic-gate brnz,pt %g5, .setup_v9utrap 16490Sstevel@tonic-gate nop 16500Sstevel@tonic-gate1: 16510Sstevel@tonic-gate mov T_PRIV_INSTR, %g1 16520Sstevel@tonic-gate 16530Sstevel@tonic-gate.mmu_exception_end: 16540Sstevel@tonic-gate CPU_INDEX(%g4, %g5) 16550Sstevel@tonic-gate set cpu_core, %g5 16560Sstevel@tonic-gate sllx %g4, CPU_CORE_SHIFT, %g4 16570Sstevel@tonic-gate add %g4, %g5, %g4 16580Sstevel@tonic-gate lduh [%g4 + CPUC_DTRACE_FLAGS], %g5 16590Sstevel@tonic-gate andcc %g5, CPU_DTRACE_NOFAULT, %g0 16600Sstevel@tonic-gate bz %xcc, .mmu_exception_tlb_chk 16610Sstevel@tonic-gate or %g5, CPU_DTRACE_BADADDR, %g5 16620Sstevel@tonic-gate stuh %g5, [%g4 + CPUC_DTRACE_FLAGS] 16630Sstevel@tonic-gate done 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate.mmu_exception_tlb_chk: 16660Sstevel@tonic-gate GET_CPU_IMPL(%g5) ! check SFSR.FT to see if this 16670Sstevel@tonic-gate cmp %g5, PANTHER_IMPL ! is a TLB parity error. But 16680Sstevel@tonic-gate bne 2f ! we only do this check while 16690Sstevel@tonic-gate mov 1, %g4 ! running on Panther CPUs 16700Sstevel@tonic-gate sllx %g4, PN_SFSR_PARITY_SHIFT, %g4 ! since US-I/II use the same 16710Sstevel@tonic-gate andcc %g3, %g4, %g0 ! bit for something else which 16720Sstevel@tonic-gate bz 2f ! will be handled later. 16730Sstevel@tonic-gate nop 16740Sstevel@tonic-gate.mmu_exception_is_tlb_parity: 16750Sstevel@tonic-gate .weak itlb_parity_trap 16760Sstevel@tonic-gate .weak dtlb_parity_trap 16770Sstevel@tonic-gate set itlb_parity_trap, %g4 16780Sstevel@tonic-gate cmp %g1, T_INSTR_EXCEPTION ! branch to the itlb or 16790Sstevel@tonic-gate be 3f ! dtlb parity handler 16800Sstevel@tonic-gate nop ! if this trap is due 16810Sstevel@tonic-gate set dtlb_parity_trap, %g4 16820Sstevel@tonic-gate cmp %g1, T_DATA_EXCEPTION ! to a IMMU exception 16830Sstevel@tonic-gate be 3f ! or DMMU exception. 16844127Sedp nop 16850Sstevel@tonic-gate2: 16860Sstevel@tonic-gate sllx %g3, 32, %g3 16870Sstevel@tonic-gate or %g3, %g1, %g3 16880Sstevel@tonic-gate set trap, %g1 16890Sstevel@tonic-gate ba,pt %xcc, sys_trap 16900Sstevel@tonic-gate sub %g0, 1, %g4 16910Sstevel@tonic-gate3: 16920Sstevel@tonic-gate jmp %g4 ! off to the appropriate 16930Sstevel@tonic-gate nop ! TLB parity handler 16940Sstevel@tonic-gate 16950Sstevel@tonic-gate.fp_disabled: 16960Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16970Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16980Sstevel@tonic-gate#ifdef SF_ERRATA_30 /* call causes fp-disabled */ 16990Sstevel@tonic-gate brz,a,pn %g1, 2f 17000Sstevel@tonic-gate nop 17010Sstevel@tonic-gate#endif 17020Sstevel@tonic-gate rdpr %tstate, %g4 17030Sstevel@tonic-gate btst TSTATE_PRIV, %g4 17040Sstevel@tonic-gate#ifdef SF_ERRATA_30 /* call causes fp-disabled */ 17050Sstevel@tonic-gate bnz,pn %icc, 2f 17060Sstevel@tonic-gate nop 17070Sstevel@tonic-gate#else 17080Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 17090Sstevel@tonic-gate mov PTL1_BAD_FPTRAP, %g1 17100Sstevel@tonic-gate#endif 17110Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 17120Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 17130Sstevel@tonic-gate brz,a,pt %g5, 2f 17140Sstevel@tonic-gate nop 17150Sstevel@tonic-gate ldn [%g5 + P_UTRAP7], %g5 ! fp_disabled utrap? 17160Sstevel@tonic-gate brz,a,pn %g5, 2f 17170Sstevel@tonic-gate nop 17180Sstevel@tonic-gate btst 1, %sp 17190Sstevel@tonic-gate bz,a,pt %xcc, 1f ! 32 bit user program 17200Sstevel@tonic-gate nop 17210Sstevel@tonic-gate ba,a,pt %xcc, .setup_v9utrap ! 64 bit user program 17220Sstevel@tonic-gate nop 17230Sstevel@tonic-gate1: 17240Sstevel@tonic-gate ba,pt %xcc, .setup_utrap 17250Sstevel@tonic-gate or %g0, %g0, %g7 17260Sstevel@tonic-gate2: 17270Sstevel@tonic-gate set fp_disabled, %g1 17280Sstevel@tonic-gate ba,pt %xcc, sys_trap 17290Sstevel@tonic-gate sub %g0, 1, %g4 17300Sstevel@tonic-gate 17310Sstevel@tonic-gate.fp_ieee_exception: 17320Sstevel@tonic-gate rdpr %tstate, %g1 17330Sstevel@tonic-gate btst TSTATE_PRIV, %g1 17340Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 17350Sstevel@tonic-gate mov PTL1_BAD_FPTRAP, %g1 17360Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 17370Sstevel@tonic-gate stx %fsr, [%g1 + CPU_TMP1] 17380Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %g2 17390Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 17400Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 17410Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 17420Sstevel@tonic-gate brz,a,pt %g5, 1f 17430Sstevel@tonic-gate nop 17440Sstevel@tonic-gate ldn [%g5 + P_UTRAP8], %g5 17450Sstevel@tonic-gate brnz,a,pt %g5, .setup_v9utrap 17460Sstevel@tonic-gate nop 17470Sstevel@tonic-gate1: 17480Sstevel@tonic-gate set _fp_ieee_exception, %g1 17490Sstevel@tonic-gate ba,pt %xcc, sys_trap 17500Sstevel@tonic-gate sub %g0, 1, %g4 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate/* 17530Sstevel@tonic-gate * Register Inputs: 17540Sstevel@tonic-gate * %g5 user trap handler 17550Sstevel@tonic-gate * %g7 misaligned addr - for alignment traps only 17560Sstevel@tonic-gate */ 17570Sstevel@tonic-gate.setup_utrap: 17580Sstevel@tonic-gate set trap, %g1 ! setup in case we go 17590Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 ! through sys_trap on 17600Sstevel@tonic-gate sub %g0, 1, %g4 ! the save instruction below 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate /* 17630Sstevel@tonic-gate * If the DTrace pid provider is single stepping a copied-out 17640Sstevel@tonic-gate * instruction, t->t_dtrace_step will be set. In that case we need 17650Sstevel@tonic-gate * to abort the single-stepping (since execution of the instruction 17660Sstevel@tonic-gate * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 17670Sstevel@tonic-gate */ 17680Sstevel@tonic-gate save %sp, -SA(MINFRAME32), %sp ! window for trap handler 17690Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 17700Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 17710Sstevel@tonic-gate ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step 17720Sstevel@tonic-gate rdpr %tnpc, %l2 ! arg1 == tnpc 17730Sstevel@tonic-gate brz,pt %g2, 1f 17740Sstevel@tonic-gate rdpr %tpc, %l1 ! arg0 == tpc 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast 17770Sstevel@tonic-gate ldn [%g1 + T_DTRACE_NPC], %l2 ! arg1 = t->t_dtrace_npc (step) 17780Sstevel@tonic-gate brz,pt %g2, 1f 17790Sstevel@tonic-gate st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags 17800Sstevel@tonic-gate stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast 17810Sstevel@tonic-gate1: 17820Sstevel@tonic-gate mov %g7, %l3 ! arg2 == misaligned address 17830Sstevel@tonic-gate 17840Sstevel@tonic-gate rdpr %tstate, %g1 ! cwp for trap handler 17850Sstevel@tonic-gate rdpr %cwp, %g4 17860Sstevel@tonic-gate bclr TSTATE_CWP_MASK, %g1 17870Sstevel@tonic-gate wrpr %g1, %g4, %tstate 17880Sstevel@tonic-gate wrpr %g0, %g5, %tnpc ! trap handler address 17890Sstevel@tonic-gate FAST_TRAP_DONE 17900Sstevel@tonic-gate /* NOTREACHED */ 17910Sstevel@tonic-gate 17920Sstevel@tonic-gate.check_v9utrap: 17930Sstevel@tonic-gate rdpr %tstate, %g1 17940Sstevel@tonic-gate btst TSTATE_PRIV, %g1 17950Sstevel@tonic-gate bnz,a,pn %icc, 3f 17960Sstevel@tonic-gate nop 17970Sstevel@tonic-gate CPU_ADDR(%g4, %g1) ! load CPU struct addr 17980Sstevel@tonic-gate ldn [%g4 + CPU_THREAD], %g5 ! load thread pointer 17990Sstevel@tonic-gate ldn [%g5 + T_PROCP], %g5 ! load proc pointer 18000Sstevel@tonic-gate ldn [%g5 + P_UTRAPS], %g5 ! are there utraps? 18010Sstevel@tonic-gate 18020Sstevel@tonic-gate cmp %g3, T_SOFTWARE_TRAP 18030Sstevel@tonic-gate bne,a,pt %icc, 1f 18040Sstevel@tonic-gate nop 18050Sstevel@tonic-gate 18060Sstevel@tonic-gate brz,pt %g5, 3f ! if p_utraps == NULL goto trap() 18070Sstevel@tonic-gate rdpr %tt, %g3 ! delay - get actual hw trap type 18084127Sedp 18090Sstevel@tonic-gate sub %g3, 254, %g1 ! UT_TRAP_INSTRUCTION_16 = p_utraps[18] 18100Sstevel@tonic-gate ba,pt %icc, 2f 18110Sstevel@tonic-gate smul %g1, CPTRSIZE, %g2 18120Sstevel@tonic-gate1: 18130Sstevel@tonic-gate brz,a,pt %g5, 3f ! if p_utraps == NULL goto trap() 18140Sstevel@tonic-gate nop 18150Sstevel@tonic-gate 18160Sstevel@tonic-gate cmp %g3, T_UNIMP_INSTR 18170Sstevel@tonic-gate bne,a,pt %icc, 2f 18180Sstevel@tonic-gate nop 18190Sstevel@tonic-gate 18200Sstevel@tonic-gate mov 1, %g1 18210Sstevel@tonic-gate st %g1, [%g4 + CPU_TL1_HDLR] ! set CPU_TL1_HDLR 18224127Sedp rdpr %tpc, %g1 ! ld trapping instruction using 18230Sstevel@tonic-gate lduwa [%g1]ASI_AIUP, %g1 ! "AS IF USER" ASI which could fault 18240Sstevel@tonic-gate st %g0, [%g4 + CPU_TL1_HDLR] ! clr CPU_TL1_HDLR 18250Sstevel@tonic-gate 18260Sstevel@tonic-gate sethi %hi(0xc1c00000), %g4 ! setup mask for illtrap instruction 18270Sstevel@tonic-gate andcc %g1, %g4, %g4 ! and instruction with mask 18280Sstevel@tonic-gate bnz,a,pt %icc, 3f ! if %g4 == zero, %g1 is an ILLTRAP 18290Sstevel@tonic-gate nop ! fall thru to setup 18304127Sedp2: 18310Sstevel@tonic-gate ldn [%g5 + %g2], %g5 18320Sstevel@tonic-gate brnz,a,pt %g5, .setup_v9utrap 18330Sstevel@tonic-gate nop 18340Sstevel@tonic-gate3: 18350Sstevel@tonic-gate set trap, %g1 18360Sstevel@tonic-gate ba,pt %xcc, sys_trap 18370Sstevel@tonic-gate sub %g0, 1, %g4 18380Sstevel@tonic-gate /* NOTREACHED */ 18390Sstevel@tonic-gate 18400Sstevel@tonic-gate/* 18410Sstevel@tonic-gate * Register Inputs: 18420Sstevel@tonic-gate * %g5 user trap handler 18430Sstevel@tonic-gate */ 18440Sstevel@tonic-gate.setup_v9utrap: 18450Sstevel@tonic-gate set trap, %g1 ! setup in case we go 18460Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 ! through sys_trap on 18470Sstevel@tonic-gate sub %g0, 1, %g4 ! the save instruction below 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate /* 18500Sstevel@tonic-gate * If the DTrace pid provider is single stepping a copied-out 18510Sstevel@tonic-gate * instruction, t->t_dtrace_step will be set. In that case we need 18520Sstevel@tonic-gate * to abort the single-stepping (since execution of the instruction 18530Sstevel@tonic-gate * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 18540Sstevel@tonic-gate */ 18550Sstevel@tonic-gate save %sp, -SA(MINFRAME64), %sp ! window for trap handler 18560Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 18570Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 18580Sstevel@tonic-gate ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step 18590Sstevel@tonic-gate rdpr %tnpc, %l7 ! arg1 == tnpc 18600Sstevel@tonic-gate brz,pt %g2, 1f 18610Sstevel@tonic-gate rdpr %tpc, %l6 ! arg0 == tpc 18620Sstevel@tonic-gate 18630Sstevel@tonic-gate ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast 18640Sstevel@tonic-gate ldn [%g1 + T_DTRACE_NPC], %l7 ! arg1 == t->t_dtrace_npc (step) 18650Sstevel@tonic-gate brz,pt %g2, 1f 18660Sstevel@tonic-gate st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags 18670Sstevel@tonic-gate stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast 18680Sstevel@tonic-gate1: 18690Sstevel@tonic-gate rdpr %tstate, %g2 ! cwp for trap handler 18700Sstevel@tonic-gate rdpr %cwp, %g4 18710Sstevel@tonic-gate bclr TSTATE_CWP_MASK, %g2 18720Sstevel@tonic-gate wrpr %g2, %g4, %tstate 18730Sstevel@tonic-gate 18740Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g4 ! load proc pointer 18750Sstevel@tonic-gate ldn [%g4 + P_AS], %g4 ! load as pointer 18760Sstevel@tonic-gate ldn [%g4 + A_USERLIMIT], %g4 ! load as userlimit 18770Sstevel@tonic-gate cmp %l7, %g4 ! check for single-step set 18780Sstevel@tonic-gate bne,pt %xcc, 4f 18790Sstevel@tonic-gate nop 18800Sstevel@tonic-gate ldn [%g1 + T_LWP], %g1 ! load klwp pointer 18810Sstevel@tonic-gate ld [%g1 + PCB_STEP], %g4 ! load single-step flag 18820Sstevel@tonic-gate cmp %g4, STEP_ACTIVE ! step flags set in pcb? 18830Sstevel@tonic-gate bne,pt %icc, 4f 18840Sstevel@tonic-gate nop 18850Sstevel@tonic-gate stn %g5, [%g1 + PCB_TRACEPC] ! save trap handler addr in pcb 18860Sstevel@tonic-gate mov %l7, %g4 ! on entry to precise user trap 18870Sstevel@tonic-gate add %l6, 4, %l7 ! handler, %l6 == pc, %l7 == npc 18880Sstevel@tonic-gate ! at time of trap 18890Sstevel@tonic-gate wrpr %g0, %g4, %tnpc ! generate FLTBOUNDS, 18900Sstevel@tonic-gate ! %g4 == userlimit 18910Sstevel@tonic-gate FAST_TRAP_DONE 18920Sstevel@tonic-gate /* NOTREACHED */ 18930Sstevel@tonic-gate4: 18940Sstevel@tonic-gate wrpr %g0, %g5, %tnpc ! trap handler address 18950Sstevel@tonic-gate FAST_TRAP_DONE_CHK_INTR 18960Sstevel@tonic-gate /* NOTREACHED */ 18970Sstevel@tonic-gate 18980Sstevel@tonic-gate.fp_exception: 18990Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 19000Sstevel@tonic-gate stx %fsr, [%g1 + CPU_TMP1] 19010Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %g2 19020Sstevel@tonic-gate 19030Sstevel@tonic-gate /* 19040Sstevel@tonic-gate * Cheetah takes unfinished_FPop trap for certain range of operands 19050Sstevel@tonic-gate * to the "fitos" instruction. Instead of going through the slow 19060Sstevel@tonic-gate * software emulation path, we try to simulate the "fitos" instruction 19070Sstevel@tonic-gate * via "fitod" and "fdtos" provided the following conditions are met: 19080Sstevel@tonic-gate * 19090Sstevel@tonic-gate * fpu_exists is set (if DEBUG) 19100Sstevel@tonic-gate * not in privileged mode 19110Sstevel@tonic-gate * ftt is unfinished_FPop 19120Sstevel@tonic-gate * NXM IEEE trap is not enabled 19130Sstevel@tonic-gate * instruction at %tpc is "fitos" 19140Sstevel@tonic-gate * 19150Sstevel@tonic-gate * Usage: 19160Sstevel@tonic-gate * %g1 per cpu address 19170Sstevel@tonic-gate * %g2 %fsr 19180Sstevel@tonic-gate * %g6 user instruction 19190Sstevel@tonic-gate * 19200Sstevel@tonic-gate * Note that we can take a memory access related trap while trying 19210Sstevel@tonic-gate * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR 19220Sstevel@tonic-gate * flag to catch those traps and let the SFMMU code deal with page 19230Sstevel@tonic-gate * fault and data access exception. 19240Sstevel@tonic-gate */ 19250Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 19260Sstevel@tonic-gate sethi %hi(fpu_exists), %g7 19270Sstevel@tonic-gate ld [%g7 + %lo(fpu_exists)], %g7 19280Sstevel@tonic-gate brz,pn %g7, .fp_exception_cont 19290Sstevel@tonic-gate nop 19300Sstevel@tonic-gate#endif 19310Sstevel@tonic-gate rdpr %tstate, %g7 ! branch if in privileged mode 19320Sstevel@tonic-gate btst TSTATE_PRIV, %g7 19330Sstevel@tonic-gate bnz,pn %xcc, .fp_exception_cont 19340Sstevel@tonic-gate srl %g2, FSR_FTT_SHIFT, %g7 ! extract ftt from %fsr 19350Sstevel@tonic-gate and %g7, (FSR_FTT>>FSR_FTT_SHIFT), %g7 19360Sstevel@tonic-gate cmp %g7, FTT_UNFIN 19374127Sedp set FSR_TEM_NX, %g5 19380Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if NOT unfinished_FPop 19390Sstevel@tonic-gate andcc %g2, %g5, %g0 19400Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if FSR_TEM_NX enabled 19410Sstevel@tonic-gate rdpr %tpc, %g5 ! get faulting PC 19420Sstevel@tonic-gate 19430Sstevel@tonic-gate or %g0, 1, %g7 19440Sstevel@tonic-gate st %g7, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 19450Sstevel@tonic-gate lda [%g5]ASI_USER, %g6 ! get user's instruction 19460Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 19470Sstevel@tonic-gate 19480Sstevel@tonic-gate set FITOS_INSTR_MASK, %g7 19490Sstevel@tonic-gate and %g6, %g7, %g7 19500Sstevel@tonic-gate set FITOS_INSTR, %g5 19510Sstevel@tonic-gate cmp %g7, %g5 19520Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if not FITOS_INSTR 19530Sstevel@tonic-gate nop 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate /* 19560Sstevel@tonic-gate * This is unfinished FPops trap for "fitos" instruction. We 19570Sstevel@tonic-gate * need to simulate "fitos" via "fitod" and "fdtos" instruction 19580Sstevel@tonic-gate * sequence. 19590Sstevel@tonic-gate * 19600Sstevel@tonic-gate * We need a temporary FP register to do the conversion. Since 19610Sstevel@tonic-gate * both source and destination operands for the "fitos" instruction 19620Sstevel@tonic-gate * have to be within %f0-%f31, we use an FP register from the upper 19630Sstevel@tonic-gate * half to guarantee that it won't collide with the source or the 19640Sstevel@tonic-gate * dest operand. However, we do have to save and restore its value. 19650Sstevel@tonic-gate * 19660Sstevel@tonic-gate * We use %d62 as a temporary FP register for the conversion and 19670Sstevel@tonic-gate * branch to appropriate instruction within the conversion tables 19680Sstevel@tonic-gate * based upon the rs2 and rd values. 19690Sstevel@tonic-gate */ 19700Sstevel@tonic-gate 19710Sstevel@tonic-gate std %d62, [%g1 + CPU_TMP1] ! save original value 19720Sstevel@tonic-gate 19730Sstevel@tonic-gate srl %g6, FITOS_RS2_SHIFT, %g7 19740Sstevel@tonic-gate and %g7, FITOS_REG_MASK, %g7 19750Sstevel@tonic-gate set _fitos_fitod_table, %g4 19760Sstevel@tonic-gate sllx %g7, 2, %g7 19770Sstevel@tonic-gate jmp %g4 + %g7 19780Sstevel@tonic-gate ba,pt %xcc, _fitos_fitod_done 19790Sstevel@tonic-gate .empty 19800Sstevel@tonic-gate 19810Sstevel@tonic-gate_fitos_fitod_table: 19820Sstevel@tonic-gate fitod %f0, %d62 19830Sstevel@tonic-gate fitod %f1, %d62 19840Sstevel@tonic-gate fitod %f2, %d62 19850Sstevel@tonic-gate fitod %f3, %d62 19860Sstevel@tonic-gate fitod %f4, %d62 19870Sstevel@tonic-gate fitod %f5, %d62 19880Sstevel@tonic-gate fitod %f6, %d62 19890Sstevel@tonic-gate fitod %f7, %d62 19900Sstevel@tonic-gate fitod %f8, %d62 19910Sstevel@tonic-gate fitod %f9, %d62 19920Sstevel@tonic-gate fitod %f10, %d62 19930Sstevel@tonic-gate fitod %f11, %d62 19940Sstevel@tonic-gate fitod %f12, %d62 19950Sstevel@tonic-gate fitod %f13, %d62 19960Sstevel@tonic-gate fitod %f14, %d62 19970Sstevel@tonic-gate fitod %f15, %d62 19980Sstevel@tonic-gate fitod %f16, %d62 19990Sstevel@tonic-gate fitod %f17, %d62 20000Sstevel@tonic-gate fitod %f18, %d62 20010Sstevel@tonic-gate fitod %f19, %d62 20020Sstevel@tonic-gate fitod %f20, %d62 20030Sstevel@tonic-gate fitod %f21, %d62 20040Sstevel@tonic-gate fitod %f22, %d62 20050Sstevel@tonic-gate fitod %f23, %d62 20060Sstevel@tonic-gate fitod %f24, %d62 20070Sstevel@tonic-gate fitod %f25, %d62 20080Sstevel@tonic-gate fitod %f26, %d62 20090Sstevel@tonic-gate fitod %f27, %d62 20100Sstevel@tonic-gate fitod %f28, %d62 20110Sstevel@tonic-gate fitod %f29, %d62 20120Sstevel@tonic-gate fitod %f30, %d62 20130Sstevel@tonic-gate fitod %f31, %d62 20140Sstevel@tonic-gate_fitos_fitod_done: 20150Sstevel@tonic-gate 20160Sstevel@tonic-gate /* 20170Sstevel@tonic-gate * Now convert data back into single precision 20180Sstevel@tonic-gate */ 20190Sstevel@tonic-gate srl %g6, FITOS_RD_SHIFT, %g7 20200Sstevel@tonic-gate and %g7, FITOS_REG_MASK, %g7 20210Sstevel@tonic-gate set _fitos_fdtos_table, %g4 20220Sstevel@tonic-gate sllx %g7, 2, %g7 20230Sstevel@tonic-gate jmp %g4 + %g7 20240Sstevel@tonic-gate ba,pt %xcc, _fitos_fdtos_done 20250Sstevel@tonic-gate .empty 20260Sstevel@tonic-gate 20270Sstevel@tonic-gate_fitos_fdtos_table: 20280Sstevel@tonic-gate fdtos %d62, %f0 20290Sstevel@tonic-gate fdtos %d62, %f1 20300Sstevel@tonic-gate fdtos %d62, %f2 20310Sstevel@tonic-gate fdtos %d62, %f3 20320Sstevel@tonic-gate fdtos %d62, %f4 20330Sstevel@tonic-gate fdtos %d62, %f5 20340Sstevel@tonic-gate fdtos %d62, %f6 20350Sstevel@tonic-gate fdtos %d62, %f7 20360Sstevel@tonic-gate fdtos %d62, %f8 20370Sstevel@tonic-gate fdtos %d62, %f9 20380Sstevel@tonic-gate fdtos %d62, %f10 20390Sstevel@tonic-gate fdtos %d62, %f11 20400Sstevel@tonic-gate fdtos %d62, %f12 20410Sstevel@tonic-gate fdtos %d62, %f13 20420Sstevel@tonic-gate fdtos %d62, %f14 20430Sstevel@tonic-gate fdtos %d62, %f15 20440Sstevel@tonic-gate fdtos %d62, %f16 20450Sstevel@tonic-gate fdtos %d62, %f17 20460Sstevel@tonic-gate fdtos %d62, %f18 20470Sstevel@tonic-gate fdtos %d62, %f19 20480Sstevel@tonic-gate fdtos %d62, %f20 20490Sstevel@tonic-gate fdtos %d62, %f21 20500Sstevel@tonic-gate fdtos %d62, %f22 20510Sstevel@tonic-gate fdtos %d62, %f23 20520Sstevel@tonic-gate fdtos %d62, %f24 20530Sstevel@tonic-gate fdtos %d62, %f25 20540Sstevel@tonic-gate fdtos %d62, %f26 20550Sstevel@tonic-gate fdtos %d62, %f27 20560Sstevel@tonic-gate fdtos %d62, %f28 20570Sstevel@tonic-gate fdtos %d62, %f29 20580Sstevel@tonic-gate fdtos %d62, %f30 20590Sstevel@tonic-gate fdtos %d62, %f31 20600Sstevel@tonic-gate_fitos_fdtos_done: 20610Sstevel@tonic-gate 20620Sstevel@tonic-gate ldd [%g1 + CPU_TMP1], %d62 ! restore %d62 20630Sstevel@tonic-gate 20640Sstevel@tonic-gate#if DEBUG 20650Sstevel@tonic-gate /* 20660Sstevel@tonic-gate * Update FPop_unfinished trap kstat 20670Sstevel@tonic-gate */ 20680Sstevel@tonic-gate set fpustat+FPUSTAT_UNFIN_KSTAT, %g7 20690Sstevel@tonic-gate ldx [%g7], %g5 20700Sstevel@tonic-gate1: 20710Sstevel@tonic-gate add %g5, 1, %g6 20724127Sedp 20730Sstevel@tonic-gate casxa [%g7] ASI_N, %g5, %g6 20740Sstevel@tonic-gate cmp %g5, %g6 20750Sstevel@tonic-gate bne,a,pn %xcc, 1b 20760Sstevel@tonic-gate or %g0, %g6, %g5 20770Sstevel@tonic-gate 20780Sstevel@tonic-gate /* 20790Sstevel@tonic-gate * Update fpu_sim_fitos kstat 20800Sstevel@tonic-gate */ 20810Sstevel@tonic-gate set fpuinfo+FPUINFO_FITOS_KSTAT, %g7 20820Sstevel@tonic-gate ldx [%g7], %g5 20830Sstevel@tonic-gate1: 20840Sstevel@tonic-gate add %g5, 1, %g6 20850Sstevel@tonic-gate 20860Sstevel@tonic-gate casxa [%g7] ASI_N, %g5, %g6 20870Sstevel@tonic-gate cmp %g5, %g6 20880Sstevel@tonic-gate bne,a,pn %xcc, 1b 20890Sstevel@tonic-gate or %g0, %g6, %g5 20900Sstevel@tonic-gate#endif /* DEBUG */ 20910Sstevel@tonic-gate 20920Sstevel@tonic-gate FAST_TRAP_DONE 20930Sstevel@tonic-gate 20940Sstevel@tonic-gate.fp_exception_cont: 20950Sstevel@tonic-gate /* 20960Sstevel@tonic-gate * Let _fp_exception deal with simulating FPop instruction. 20970Sstevel@tonic-gate * Note that we need to pass %fsr in %g2 (already read above). 20980Sstevel@tonic-gate */ 20990Sstevel@tonic-gate 21000Sstevel@tonic-gate set _fp_exception, %g1 21010Sstevel@tonic-gate ba,pt %xcc, sys_trap 21020Sstevel@tonic-gate sub %g0, 1, %g4 21030Sstevel@tonic-gate 21045414Smb158278 .global opl_cleanw_patch 21055414Smb158278opl_cleanw_patch: 21060Sstevel@tonic-gate.clean_windows: 21070Sstevel@tonic-gate set trap, %g1 21080Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 21090Sstevel@tonic-gate sub %g0, 1, %g4 21100Sstevel@tonic-gate save 21110Sstevel@tonic-gate flushw 21120Sstevel@tonic-gate restore 21130Sstevel@tonic-gate wrpr %g0, %g0, %cleanwin ! no clean windows 21140Sstevel@tonic-gate 21150Sstevel@tonic-gate CPU_ADDR(%g4, %g5) 21160Sstevel@tonic-gate ldn [%g4 + CPU_MPCB], %g4 21170Sstevel@tonic-gate brz,a,pn %g4, 1f 21180Sstevel@tonic-gate nop 21190Sstevel@tonic-gate ld [%g4 + MPCB_WSTATE], %g5 21200Sstevel@tonic-gate add %g5, WSTATE_CLEAN_OFFSET, %g5 21210Sstevel@tonic-gate wrpr %g0, %g5, %wstate 21220Sstevel@tonic-gate1: FAST_TRAP_DONE 21230Sstevel@tonic-gate 21240Sstevel@tonic-gate/* 21250Sstevel@tonic-gate * .spill_clean: clean the previous window, restore the wstate, and 21260Sstevel@tonic-gate * "done". 21270Sstevel@tonic-gate * 21280Sstevel@tonic-gate * Entry: %g7 contains new wstate 21290Sstevel@tonic-gate */ 21300Sstevel@tonic-gate.spill_clean: 21310Sstevel@tonic-gate sethi %hi(nwin_minus_one), %g5 21320Sstevel@tonic-gate ld [%g5 + %lo(nwin_minus_one)], %g5 ! %g5 = nwin - 1 21330Sstevel@tonic-gate rdpr %cwp, %g6 ! %g6 = %cwp 21340Sstevel@tonic-gate deccc %g6 ! %g6-- 21350Sstevel@tonic-gate movneg %xcc, %g5, %g6 ! if (%g6<0) %g6 = nwin-1 21360Sstevel@tonic-gate wrpr %g6, %cwp 21370Sstevel@tonic-gate TT_TRACE_L(trace_win) 21380Sstevel@tonic-gate clr %l0 21390Sstevel@tonic-gate clr %l1 21400Sstevel@tonic-gate clr %l2 21410Sstevel@tonic-gate clr %l3 21420Sstevel@tonic-gate clr %l4 21430Sstevel@tonic-gate clr %l5 21440Sstevel@tonic-gate clr %l6 21450Sstevel@tonic-gate clr %l7 21460Sstevel@tonic-gate wrpr %g0, %g7, %wstate 21470Sstevel@tonic-gate saved 21480Sstevel@tonic-gate retry ! restores correct %cwp 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate.fix_alignment: 21510Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 21520Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 21530Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 21540Sstevel@tonic-gate mov 1, %g2 21550Sstevel@tonic-gate stb %g2, [%g1 + P_FIXALIGNMENT] 21560Sstevel@tonic-gate FAST_TRAP_DONE 21570Sstevel@tonic-gate 21580Sstevel@tonic-gate#define STDF_REG(REG, ADDR, TMP) \ 21590Sstevel@tonic-gate sll REG, 3, REG ;\ 21600Sstevel@tonic-gatemark1: set start1, TMP ;\ 21610Sstevel@tonic-gate jmp REG + TMP ;\ 21620Sstevel@tonic-gate nop ;\ 21630Sstevel@tonic-gatestart1: ba,pt %xcc, done1 ;\ 21640Sstevel@tonic-gate std %f0, [ADDR + CPU_TMP1] ;\ 21650Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21660Sstevel@tonic-gate std %f32, [ADDR + CPU_TMP1] ;\ 21670Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21680Sstevel@tonic-gate std %f2, [ADDR + CPU_TMP1] ;\ 21690Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21700Sstevel@tonic-gate std %f34, [ADDR + CPU_TMP1] ;\ 21710Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21720Sstevel@tonic-gate std %f4, [ADDR + CPU_TMP1] ;\ 21730Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21740Sstevel@tonic-gate std %f36, [ADDR + CPU_TMP1] ;\ 21750Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21760Sstevel@tonic-gate std %f6, [ADDR + CPU_TMP1] ;\ 21770Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21780Sstevel@tonic-gate std %f38, [ADDR + CPU_TMP1] ;\ 21790Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21800Sstevel@tonic-gate std %f8, [ADDR + CPU_TMP1] ;\ 21810Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21820Sstevel@tonic-gate std %f40, [ADDR + CPU_TMP1] ;\ 21830Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21840Sstevel@tonic-gate std %f10, [ADDR + CPU_TMP1] ;\ 21850Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21860Sstevel@tonic-gate std %f42, [ADDR + CPU_TMP1] ;\ 21870Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21880Sstevel@tonic-gate std %f12, [ADDR + CPU_TMP1] ;\ 21890Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21900Sstevel@tonic-gate std %f44, [ADDR + CPU_TMP1] ;\ 21910Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21920Sstevel@tonic-gate std %f14, [ADDR + CPU_TMP1] ;\ 21930Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21940Sstevel@tonic-gate std %f46, [ADDR + CPU_TMP1] ;\ 21950Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21960Sstevel@tonic-gate std %f16, [ADDR + CPU_TMP1] ;\ 21970Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 21980Sstevel@tonic-gate std %f48, [ADDR + CPU_TMP1] ;\ 21990Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22000Sstevel@tonic-gate std %f18, [ADDR + CPU_TMP1] ;\ 22010Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22020Sstevel@tonic-gate std %f50, [ADDR + CPU_TMP1] ;\ 22030Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22040Sstevel@tonic-gate std %f20, [ADDR + CPU_TMP1] ;\ 22050Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22060Sstevel@tonic-gate std %f52, [ADDR + CPU_TMP1] ;\ 22070Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22080Sstevel@tonic-gate std %f22, [ADDR + CPU_TMP1] ;\ 22090Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22100Sstevel@tonic-gate std %f54, [ADDR + CPU_TMP1] ;\ 22110Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22120Sstevel@tonic-gate std %f24, [ADDR + CPU_TMP1] ;\ 22130Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22140Sstevel@tonic-gate std %f56, [ADDR + CPU_TMP1] ;\ 22150Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22160Sstevel@tonic-gate std %f26, [ADDR + CPU_TMP1] ;\ 22170Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22180Sstevel@tonic-gate std %f58, [ADDR + CPU_TMP1] ;\ 22190Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22200Sstevel@tonic-gate std %f28, [ADDR + CPU_TMP1] ;\ 22210Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22220Sstevel@tonic-gate std %f60, [ADDR + CPU_TMP1] ;\ 22230Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22240Sstevel@tonic-gate std %f30, [ADDR + CPU_TMP1] ;\ 22250Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 22260Sstevel@tonic-gate std %f62, [ADDR + CPU_TMP1] ;\ 22270Sstevel@tonic-gatedone1: 22280Sstevel@tonic-gate 22290Sstevel@tonic-gate#define LDDF_REG(REG, ADDR, TMP) \ 22300Sstevel@tonic-gate sll REG, 3, REG ;\ 22310Sstevel@tonic-gatemark2: set start2, TMP ;\ 22320Sstevel@tonic-gate jmp REG + TMP ;\ 22330Sstevel@tonic-gate nop ;\ 22340Sstevel@tonic-gatestart2: ba,pt %xcc, done2 ;\ 22350Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f0 ;\ 22360Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22370Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f32 ;\ 22380Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22390Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f2 ;\ 22400Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22410Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f34 ;\ 22420Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22430Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f4 ;\ 22440Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22450Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f36 ;\ 22460Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22470Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f6 ;\ 22480Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22490Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f38 ;\ 22500Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22510Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f8 ;\ 22520Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22530Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f40 ;\ 22540Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22550Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f10 ;\ 22560Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22570Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f42 ;\ 22580Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22590Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f12 ;\ 22600Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22610Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f44 ;\ 22620Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22630Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f14 ;\ 22640Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22650Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f46 ;\ 22660Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22670Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f16 ;\ 22680Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22690Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f48 ;\ 22700Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22710Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f18 ;\ 22720Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22730Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f50 ;\ 22740Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22750Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f20 ;\ 22760Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22770Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f52 ;\ 22780Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22790Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f22 ;\ 22800Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22810Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f54 ;\ 22820Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22830Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f24 ;\ 22840Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22850Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f56 ;\ 22860Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22870Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f26 ;\ 22880Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22890Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f58 ;\ 22900Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22910Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f28 ;\ 22920Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22930Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f60 ;\ 22940Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22950Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f30 ;\ 22960Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 22970Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f62 ;\ 22980Sstevel@tonic-gatedone2: 22990Sstevel@tonic-gate 23000Sstevel@tonic-gate.lddf_exception_not_aligned: 23010Sstevel@tonic-gate /* 23020Sstevel@tonic-gate * Cheetah overwrites SFAR on a DTLB miss, hence read it now. 23030Sstevel@tonic-gate */ 23040Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g5 ! misaligned vaddr in %g5 23050Sstevel@tonic-gate 23060Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 23070Sstevel@tonic-gate sethi %hi(fpu_exists), %g2 ! check fpu_exists 23080Sstevel@tonic-gate ld [%g2 + %lo(fpu_exists)], %g2 23090Sstevel@tonic-gate brz,a,pn %g2, 4f 23100Sstevel@tonic-gate nop 23110Sstevel@tonic-gate#endif 23120Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23130Sstevel@tonic-gate or %g0, 1, %g4 23140Sstevel@tonic-gate st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 23150Sstevel@tonic-gate 23160Sstevel@tonic-gate rdpr %tpc, %g2 23170Sstevel@tonic-gate lda [%g2]ASI_AIUP, %g6 ! get the user's lddf instruction 23180Sstevel@tonic-gate srl %g6, 23, %g1 ! using ldda or not? 23190Sstevel@tonic-gate and %g1, 1, %g1 23200Sstevel@tonic-gate brz,a,pt %g1, 2f ! check for ldda instruction 23210Sstevel@tonic-gate nop 23220Sstevel@tonic-gate srl %g6, 13, %g1 ! check immflag 23230Sstevel@tonic-gate and %g1, 1, %g1 23240Sstevel@tonic-gate rdpr %tstate, %g2 ! %tstate in %g2 23250Sstevel@tonic-gate brnz,a,pn %g1, 1f 23260Sstevel@tonic-gate srl %g2, 31, %g1 ! get asi from %tstate 23270Sstevel@tonic-gate srl %g6, 5, %g1 ! get asi from instruction 23280Sstevel@tonic-gate and %g1, 0xFF, %g1 ! imm_asi field 23290Sstevel@tonic-gate1: 23300Sstevel@tonic-gate cmp %g1, ASI_P ! primary address space 23310Sstevel@tonic-gate be,a,pt %icc, 2f 23320Sstevel@tonic-gate nop 23330Sstevel@tonic-gate cmp %g1, ASI_PNF ! primary no fault address space 23340Sstevel@tonic-gate be,a,pt %icc, 2f 23350Sstevel@tonic-gate nop 23360Sstevel@tonic-gate cmp %g1, ASI_S ! secondary address space 23370Sstevel@tonic-gate be,a,pt %icc, 2f 23380Sstevel@tonic-gate nop 23390Sstevel@tonic-gate cmp %g1, ASI_SNF ! secondary no fault address space 23400Sstevel@tonic-gate bne,a,pn %icc, 3f 23410Sstevel@tonic-gate nop 23420Sstevel@tonic-gate2: 23430Sstevel@tonic-gate lduwa [%g5]ASI_USER, %g7 ! get first half of misaligned data 23440Sstevel@tonic-gate add %g5, 4, %g5 ! increment misaligned data address 23450Sstevel@tonic-gate lduwa [%g5]ASI_USER, %g5 ! get second half of misaligned data 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate sllx %g7, 32, %g7 23480Sstevel@tonic-gate or %g5, %g7, %g5 ! combine data 23490Sstevel@tonic-gate CPU_ADDR(%g7, %g1) ! save data on a per-cpu basis 23500Sstevel@tonic-gate stx %g5, [%g7 + CPU_TMP1] ! save in cpu_tmp1 23510Sstevel@tonic-gate 23520Sstevel@tonic-gate srl %g6, 25, %g3 ! %g6 has the instruction 23530Sstevel@tonic-gate and %g3, 0x1F, %g3 ! %g3 has rd 23540Sstevel@tonic-gate LDDF_REG(%g3, %g7, %g4) 23550Sstevel@tonic-gate 23560Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23570Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 23580Sstevel@tonic-gate FAST_TRAP_DONE 23590Sstevel@tonic-gate3: 23600Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23610Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 23620Sstevel@tonic-gate4: 23630Sstevel@tonic-gate set T_USER, %g3 ! trap type in %g3 23640Sstevel@tonic-gate or %g3, T_LDDF_ALIGN, %g3 23650Sstevel@tonic-gate mov %g5, %g2 ! misaligned vaddr in %g2 23660Sstevel@tonic-gate set fpu_trap, %g1 ! goto C for the little and 23670Sstevel@tonic-gate ba,pt %xcc, sys_trap ! no fault little asi's 23680Sstevel@tonic-gate sub %g0, 1, %g4 23690Sstevel@tonic-gate 23700Sstevel@tonic-gate.stdf_exception_not_aligned: 23710Sstevel@tonic-gate /* 23720Sstevel@tonic-gate * Cheetah overwrites SFAR on a DTLB miss, hence read it now. 23730Sstevel@tonic-gate */ 23740Sstevel@tonic-gate ldxa [MMU_SFAR]%asi, %g5 ! misaligned vaddr in %g5 23750Sstevel@tonic-gate 23760Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 23770Sstevel@tonic-gate sethi %hi(fpu_exists), %g7 ! check fpu_exists 23780Sstevel@tonic-gate ld [%g7 + %lo(fpu_exists)], %g3 23790Sstevel@tonic-gate brz,a,pn %g3, 4f 23800Sstevel@tonic-gate nop 23810Sstevel@tonic-gate#endif 23820Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 23830Sstevel@tonic-gate or %g0, 1, %g4 23840Sstevel@tonic-gate st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 23850Sstevel@tonic-gate 23860Sstevel@tonic-gate rdpr %tpc, %g2 23870Sstevel@tonic-gate lda [%g2]ASI_AIUP, %g6 ! get the user's stdf instruction 23880Sstevel@tonic-gate 23890Sstevel@tonic-gate srl %g6, 23, %g1 ! using stda or not? 23900Sstevel@tonic-gate and %g1, 1, %g1 23910Sstevel@tonic-gate brz,a,pt %g1, 2f ! check for stda instruction 23920Sstevel@tonic-gate nop 23930Sstevel@tonic-gate srl %g6, 13, %g1 ! check immflag 23940Sstevel@tonic-gate and %g1, 1, %g1 23950Sstevel@tonic-gate rdpr %tstate, %g2 ! %tstate in %g2 23960Sstevel@tonic-gate brnz,a,pn %g1, 1f 23970Sstevel@tonic-gate srl %g2, 31, %g1 ! get asi from %tstate 23980Sstevel@tonic-gate srl %g6, 5, %g1 ! get asi from instruction 23990Sstevel@tonic-gate and %g1, 0xFF, %g1 ! imm_asi field 24000Sstevel@tonic-gate1: 24010Sstevel@tonic-gate cmp %g1, ASI_P ! primary address space 24020Sstevel@tonic-gate be,a,pt %icc, 2f 24030Sstevel@tonic-gate nop 24040Sstevel@tonic-gate cmp %g1, ASI_S ! secondary address space 24050Sstevel@tonic-gate bne,a,pn %icc, 3f 24060Sstevel@tonic-gate nop 24070Sstevel@tonic-gate2: 24080Sstevel@tonic-gate srl %g6, 25, %g6 24090Sstevel@tonic-gate and %g6, 0x1F, %g6 ! %g6 has rd 24100Sstevel@tonic-gate CPU_ADDR(%g7, %g1) 24110Sstevel@tonic-gate STDF_REG(%g6, %g7, %g4) ! STDF_REG(REG, ADDR, TMP) 24120Sstevel@tonic-gate 24130Sstevel@tonic-gate ldx [%g7 + CPU_TMP1], %g6 24140Sstevel@tonic-gate srlx %g6, 32, %g7 24150Sstevel@tonic-gate stuwa %g7, [%g5]ASI_USER ! first half 24160Sstevel@tonic-gate add %g5, 4, %g5 ! increment misaligned data address 24170Sstevel@tonic-gate stuwa %g6, [%g5]ASI_USER ! second half 24180Sstevel@tonic-gate 24190Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 24200Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 24210Sstevel@tonic-gate FAST_TRAP_DONE 24220Sstevel@tonic-gate3: 24230Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 24240Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 24250Sstevel@tonic-gate4: 24260Sstevel@tonic-gate set T_USER, %g3 ! trap type in %g3 24270Sstevel@tonic-gate or %g3, T_STDF_ALIGN, %g3 24280Sstevel@tonic-gate mov %g5, %g2 ! misaligned vaddr in %g2 24290Sstevel@tonic-gate set fpu_trap, %g1 ! goto C for the little and 24300Sstevel@tonic-gate ba,pt %xcc, sys_trap ! nofault little asi's 24310Sstevel@tonic-gate sub %g0, 1, %g4 24320Sstevel@tonic-gate 24330Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL 24340Sstevel@tonic-gate 24350Sstevel@tonic-gate.traptrace_freeze: 24360Sstevel@tonic-gate mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4 24370Sstevel@tonic-gate TT_TRACE_L(trace_win) 24380Sstevel@tonic-gate mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0 24390Sstevel@tonic-gate set trap_freeze, %g1 24400Sstevel@tonic-gate mov 1, %g2 24410Sstevel@tonic-gate st %g2, [%g1] 24420Sstevel@tonic-gate FAST_TRAP_DONE 24430Sstevel@tonic-gate 24440Sstevel@tonic-gate.traptrace_unfreeze: 24450Sstevel@tonic-gate set trap_freeze, %g1 24460Sstevel@tonic-gate st %g0, [%g1] 24470Sstevel@tonic-gate mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4 24480Sstevel@tonic-gate TT_TRACE_L(trace_win) 24490Sstevel@tonic-gate mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0 24500Sstevel@tonic-gate FAST_TRAP_DONE 24510Sstevel@tonic-gate 24520Sstevel@tonic-gate#endif /* DEBUG_USER_TRAPTRACECTL */ 24530Sstevel@tonic-gate 24540Sstevel@tonic-gate.getcc: 24550Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 24560Sstevel@tonic-gate stx %o0, [%g1 + CPU_TMP1] ! save %o0 24570Sstevel@tonic-gate stx %o1, [%g1 + CPU_TMP2] ! save %o1 24580Sstevel@tonic-gate rdpr %tstate, %g3 ! get tstate 24590Sstevel@tonic-gate srlx %g3, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr 24600Sstevel@tonic-gate set PSR_ICC, %g2 24610Sstevel@tonic-gate and %o0, %g2, %o0 ! mask out the rest 24620Sstevel@tonic-gate srl %o0, PSR_ICC_SHIFT, %o0 ! right justify 24630Sstevel@tonic-gate rdpr %pstate, %o1 24640Sstevel@tonic-gate wrpr %o1, PSTATE_AG, %pstate ! get into normal globals 24650Sstevel@tonic-gate mov %o0, %g1 ! move ccr to normal %g1 24660Sstevel@tonic-gate wrpr %g0, %o1, %pstate ! back into alternate globals 24670Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %o0 ! restore %o0 24680Sstevel@tonic-gate ldx [%g1 + CPU_TMP2], %o1 ! restore %o1 24690Sstevel@tonic-gate FAST_TRAP_DONE 24700Sstevel@tonic-gate 24710Sstevel@tonic-gate.setcc: 24720Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 24730Sstevel@tonic-gate stx %o0, [%g1 + CPU_TMP1] ! save %o0 24740Sstevel@tonic-gate stx %o1, [%g1 + CPU_TMP2] ! save %o1 24750Sstevel@tonic-gate rdpr %pstate, %o0 24760Sstevel@tonic-gate wrpr %o0, PSTATE_AG, %pstate ! get into normal globals 24770Sstevel@tonic-gate mov %g1, %o1 24780Sstevel@tonic-gate wrpr %g0, %o0, %pstate ! back to alternates 24790Sstevel@tonic-gate sll %o1, PSR_ICC_SHIFT, %g2 24800Sstevel@tonic-gate set PSR_ICC, %g3 24810Sstevel@tonic-gate and %g2, %g3, %g2 ! mask out rest 24820Sstevel@tonic-gate sllx %g2, PSR_TSTATE_CC_SHIFT, %g2 24830Sstevel@tonic-gate rdpr %tstate, %g3 ! get tstate 24840Sstevel@tonic-gate srl %g3, 0, %g3 ! clear upper word 24850Sstevel@tonic-gate or %g3, %g2, %g3 ! or in new bits 24860Sstevel@tonic-gate wrpr %g3, %tstate 24870Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %o0 ! restore %o0 24880Sstevel@tonic-gate ldx [%g1 + CPU_TMP2], %o1 ! restore %o1 24890Sstevel@tonic-gate FAST_TRAP_DONE 24900Sstevel@tonic-gate 24910Sstevel@tonic-gate/* 24920Sstevel@tonic-gate * getpsr(void) 24930Sstevel@tonic-gate * Note that the xcc part of the ccr is not provided. 24940Sstevel@tonic-gate * The V8 code shows why the V9 trap is not faster: 24950Sstevel@tonic-gate * #define GETPSR_TRAP() \ 24960Sstevel@tonic-gate * mov %psr, %i0; jmp %l2; rett %l2+4; nop; 24970Sstevel@tonic-gate */ 24980Sstevel@tonic-gate 24990Sstevel@tonic-gate .type .getpsr, #function 25000Sstevel@tonic-gate.getpsr: 25010Sstevel@tonic-gate rdpr %tstate, %g1 ! get tstate 25020Sstevel@tonic-gate srlx %g1, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr 25030Sstevel@tonic-gate set PSR_ICC, %g2 25040Sstevel@tonic-gate and %o0, %g2, %o0 ! mask out the rest 25050Sstevel@tonic-gate 25060Sstevel@tonic-gate rd %fprs, %g1 ! get fprs 25070Sstevel@tonic-gate and %g1, FPRS_FEF, %g2 ! mask out dirty upper/lower 25080Sstevel@tonic-gate sllx %g2, PSR_FPRS_FEF_SHIFT, %g2 ! shift fef to V8 psr.ef 25090Sstevel@tonic-gate or %o0, %g2, %o0 ! or result into psr.ef 25100Sstevel@tonic-gate 25110Sstevel@tonic-gate set V9_PSR_IMPLVER, %g2 ! SI assigned impl/ver: 0xef 25120Sstevel@tonic-gate or %o0, %g2, %o0 ! or psr.impl/ver 25130Sstevel@tonic-gate FAST_TRAP_DONE 25140Sstevel@tonic-gate SET_SIZE(.getpsr) 25150Sstevel@tonic-gate 25160Sstevel@tonic-gate/* 25170Sstevel@tonic-gate * setpsr(newpsr) 25180Sstevel@tonic-gate * Note that there is no support for ccr.xcc in the V9 code. 25190Sstevel@tonic-gate */ 25200Sstevel@tonic-gate 25210Sstevel@tonic-gate .type .setpsr, #function 25220Sstevel@tonic-gate.setpsr: 25230Sstevel@tonic-gate rdpr %tstate, %g1 ! get tstate 25240Sstevel@tonic-gate! setx TSTATE_V8_UBITS, %g2 25250Sstevel@tonic-gate or %g0, CCR_ICC, %g3 25260Sstevel@tonic-gate sllx %g3, TSTATE_CCR_SHIFT, %g2 25270Sstevel@tonic-gate 25280Sstevel@tonic-gate andn %g1, %g2, %g1 ! zero current user bits 25290Sstevel@tonic-gate set PSR_ICC, %g2 25300Sstevel@tonic-gate and %g2, %o0, %g2 ! clear all but psr.icc bits 25310Sstevel@tonic-gate sllx %g2, PSR_TSTATE_CC_SHIFT, %g3 ! shift to tstate.ccr.icc 25320Sstevel@tonic-gate wrpr %g1, %g3, %tstate ! write tstate 25330Sstevel@tonic-gate 25340Sstevel@tonic-gate set PSR_EF, %g2 25350Sstevel@tonic-gate and %g2, %o0, %g2 ! clear all but fp enable bit 25360Sstevel@tonic-gate srlx %g2, PSR_FPRS_FEF_SHIFT, %g4 ! shift ef to V9 fprs.fef 25370Sstevel@tonic-gate wr %g0, %g4, %fprs ! write fprs 25380Sstevel@tonic-gate 25390Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 25400Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 25410Sstevel@tonic-gate ldn [%g2 + T_LWP], %g3 ! load klwp pointer 25420Sstevel@tonic-gate ldn [%g3 + LWP_FPU], %g2 ! get lwp_fpu pointer 25430Sstevel@tonic-gate stuw %g4, [%g2 + FPU_FPRS] ! write fef value to fpu_fprs 25440Sstevel@tonic-gate srlx %g4, 2, %g4 ! shift fef value to bit 0 25450Sstevel@tonic-gate stub %g4, [%g2 + FPU_EN] ! write fef value to fpu_en 25460Sstevel@tonic-gate FAST_TRAP_DONE 25470Sstevel@tonic-gate SET_SIZE(.setpsr) 25480Sstevel@tonic-gate 25490Sstevel@tonic-gate/* 25500Sstevel@tonic-gate * getlgrp 25510Sstevel@tonic-gate * get home lgrpid on which the calling thread is currently executing. 25520Sstevel@tonic-gate */ 25530Sstevel@tonic-gate .type .getlgrp, #function 25540Sstevel@tonic-gate.getlgrp: 25550Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 25560Sstevel@tonic-gate ld [%g1 + CPU_ID], %o0 ! load cpu_id 25570Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 25580Sstevel@tonic-gate ldn [%g2 + T_LPL], %g2 ! load lpl pointer 25590Sstevel@tonic-gate ld [%g2 + LPL_LGRPID], %g1 ! load lpl_lgrpid 25600Sstevel@tonic-gate sra %g1, 0, %o1 25610Sstevel@tonic-gate FAST_TRAP_DONE 25620Sstevel@tonic-gate SET_SIZE(.getlgrp) 25630Sstevel@tonic-gate 25640Sstevel@tonic-gate/* 25650Sstevel@tonic-gate * Entry for old 4.x trap (trap 0). 25660Sstevel@tonic-gate */ 25670Sstevel@tonic-gate ENTRY_NP(syscall_trap_4x) 25680Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 25690Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 25700Sstevel@tonic-gate ldn [%g2 + T_LWP], %g2 ! load klwp pointer 25710Sstevel@tonic-gate ld [%g2 + PCB_TRAP0], %g2 ! lwp->lwp_pcb.pcb_trap0addr 25720Sstevel@tonic-gate brz,pn %g2, 1f ! has it been set? 25730Sstevel@tonic-gate st %l0, [%g1 + CPU_TMP1] ! delay - save some locals 25740Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 25750Sstevel@tonic-gate rdpr %tnpc, %l1 ! save old tnpc 25760Sstevel@tonic-gate wrpr %g0, %g2, %tnpc ! setup tnpc 25770Sstevel@tonic-gate 25780Sstevel@tonic-gate rdpr %pstate, %l0 25790Sstevel@tonic-gate wrpr %l0, PSTATE_AG, %pstate ! switch to normal globals 25800Sstevel@tonic-gate mov %l1, %g6 ! pass tnpc to user code in %g6 25810Sstevel@tonic-gate wrpr %l0, %g0, %pstate ! switch back to alternate globals 25820Sstevel@tonic-gate 25830Sstevel@tonic-gate ! Note that %g1 still contains CPU struct addr 25840Sstevel@tonic-gate ld [%g1 + CPU_TMP2], %l1 ! restore locals 25850Sstevel@tonic-gate ld [%g1 + CPU_TMP1], %l0 25860Sstevel@tonic-gate FAST_TRAP_DONE_CHK_INTR 25870Sstevel@tonic-gate1: 25880Sstevel@tonic-gate mov %g1, %l0 25890Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 25900Sstevel@tonic-gate rdpr %pstate, %l1 25910Sstevel@tonic-gate wrpr %l1, PSTATE_AG, %pstate 25920Sstevel@tonic-gate ! 25930Sstevel@tonic-gate ! check for old syscall mmap which is the only different one which 25940Sstevel@tonic-gate ! must be the same. Others are handled in the compatibility library. 25950Sstevel@tonic-gate ! 25960Sstevel@tonic-gate cmp %g1, OSYS_mmap ! compare to old 4.x mmap 25970Sstevel@tonic-gate movz %icc, SYS_mmap, %g1 25980Sstevel@tonic-gate wrpr %g0, %l1, %pstate 25990Sstevel@tonic-gate ld [%l0 + CPU_TMP2], %l1 ! restore locals 26000Sstevel@tonic-gate ld [%l0 + CPU_TMP1], %l0 26010Sstevel@tonic-gate SYSCALL(syscall_trap32) 26020Sstevel@tonic-gate SET_SIZE(syscall_trap_4x) 26030Sstevel@tonic-gate 26040Sstevel@tonic-gate/* 26050Sstevel@tonic-gate * Handler for software trap 9. 26060Sstevel@tonic-gate * Set trap0 emulation address for old 4.x system call trap. 26070Sstevel@tonic-gate * XXX - this should be a system call. 26080Sstevel@tonic-gate */ 26090Sstevel@tonic-gate ENTRY_NP(set_trap0_addr) 26100Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 26110Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 26120Sstevel@tonic-gate ldn [%g2 + T_LWP], %g2 ! load klwp pointer 26130Sstevel@tonic-gate st %l0, [%g1 + CPU_TMP1] ! save some locals 26140Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 26150Sstevel@tonic-gate rdpr %pstate, %l0 26160Sstevel@tonic-gate wrpr %l0, PSTATE_AG, %pstate 26170Sstevel@tonic-gate mov %g1, %l1 26180Sstevel@tonic-gate wrpr %g0, %l0, %pstate 26190Sstevel@tonic-gate andn %l1, 3, %l1 ! force alignment 26200Sstevel@tonic-gate st %l1, [%g2 + PCB_TRAP0] ! lwp->lwp_pcb.pcb_trap0addr 26210Sstevel@tonic-gate ld [%g1 + CPU_TMP1], %l0 ! restore locals 26220Sstevel@tonic-gate ld [%g1 + CPU_TMP2], %l1 26230Sstevel@tonic-gate FAST_TRAP_DONE 26240Sstevel@tonic-gate SET_SIZE(set_trap0_addr) 26250Sstevel@tonic-gate 26260Sstevel@tonic-gate/* 26270Sstevel@tonic-gate * mmu_trap_tl1 26280Sstevel@tonic-gate * trap handler for unexpected mmu traps. 26290Sstevel@tonic-gate * simply checks if the trap was a user lddf/stdf alignment trap, in which 26300Sstevel@tonic-gate * case we go to fpu_trap or a user trap from the window handler, in which 26310Sstevel@tonic-gate * case we go save the state on the pcb. Otherwise, we go to ptl1_panic. 26320Sstevel@tonic-gate */ 26330Sstevel@tonic-gate .type mmu_trap_tl1, #function 26340Sstevel@tonic-gatemmu_trap_tl1: 26350Sstevel@tonic-gate#ifdef TRAPTRACE 26360Sstevel@tonic-gate TRACE_PTR(%g5, %g6) 2637*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g7) 26380Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_TICK]%asi 26390Sstevel@tonic-gate rdpr %tl, %g6 26400Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TL]%asi 26410Sstevel@tonic-gate rdpr %tt, %g6 26420Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TT]%asi 26430Sstevel@tonic-gate rdpr %tstate, %g6 26440Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi 26450Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 26460Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 26470Sstevel@tonic-gate rdpr %tpc, %g6 26480Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_TPC]%asi 26490Sstevel@tonic-gate set MMU_SFAR, %g6 26500Sstevel@tonic-gate ldxa [%g6]ASI_DMMU, %g6 26510Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_F1]%asi 26520Sstevel@tonic-gate CPU_PADDR(%g7, %g6); 26530Sstevel@tonic-gate add %g7, CPU_TL1_HDLR, %g7 26540Sstevel@tonic-gate lda [%g7]ASI_MEM, %g6 26550Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_F2]%asi 26560Sstevel@tonic-gate set 0xdeadbeef, %g6 26570Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F3]%asi 26580Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F4]%asi 26590Sstevel@tonic-gate TRACE_NEXT(%g5, %g6, %g7) 26600Sstevel@tonic-gate#endif /* TRAPTRACE */ 26610Sstevel@tonic-gate 26620Sstevel@tonic-gate GET_CPU_IMPL(%g5) 26630Sstevel@tonic-gate cmp %g5, PANTHER_IMPL 26640Sstevel@tonic-gate bne mmu_trap_tl1_4 26650Sstevel@tonic-gate nop 26660Sstevel@tonic-gate rdpr %tt, %g5 26670Sstevel@tonic-gate cmp %g5, T_DATA_EXCEPTION 26680Sstevel@tonic-gate bne mmu_trap_tl1_4 26690Sstevel@tonic-gate nop 26700Sstevel@tonic-gate wr %g0, ASI_DMMU, %asi 26710Sstevel@tonic-gate ldxa [MMU_SFSR]%asi, %g5 26720Sstevel@tonic-gate mov 1, %g6 26730Sstevel@tonic-gate sllx %g6, PN_SFSR_PARITY_SHIFT, %g6 26740Sstevel@tonic-gate andcc %g5, %g6, %g0 26750Sstevel@tonic-gate bz mmu_trap_tl1_4 26760Sstevel@tonic-gate 26770Sstevel@tonic-gate /* 26780Sstevel@tonic-gate * We are running on a Panther and have hit a DTLB parity error. 26790Sstevel@tonic-gate */ 26800Sstevel@tonic-gate ldxa [MMU_TAG_ACCESS]%asi, %g2 26810Sstevel@tonic-gate mov %g5, %g3 26820Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_is_tlb_parity 26830Sstevel@tonic-gate mov T_DATA_EXCEPTION, %g1 26840Sstevel@tonic-gate 26850Sstevel@tonic-gatemmu_trap_tl1_4: 26860Sstevel@tonic-gate CPU_PADDR(%g7, %g6); 26870Sstevel@tonic-gate add %g7, CPU_TL1_HDLR, %g7 ! %g7 = &cpu_m.tl1_hdlr (PA) 26880Sstevel@tonic-gate /* 26890Sstevel@tonic-gate * AM is cleared on trap, so addresses are 64 bit 26900Sstevel@tonic-gate */ 26910Sstevel@tonic-gate lda [%g7]ASI_MEM, %g6 26920Sstevel@tonic-gate brz,a,pt %g6, 1f 26930Sstevel@tonic-gate nop 26940Sstevel@tonic-gate /* 26950Sstevel@tonic-gate * We are going to update cpu_m.tl1_hdlr using physical address. 26960Sstevel@tonic-gate * Flush the D$ line, so that stale data won't be accessed later. 26970Sstevel@tonic-gate */ 26980Sstevel@tonic-gate CPU_ADDR(%g6, %g5) 26990Sstevel@tonic-gate add %g6, CPU_TL1_HDLR, %g6 ! %g6 = &cpu_m.tl1_hdlr (VA) 27000Sstevel@tonic-gate GET_CPU_IMPL(%g5) 27010Sstevel@tonic-gate cmp %g5, CHEETAH_IMPL 27021772Sjl139090 bl,pt %icc, 3f 27031772Sjl139090 cmp %g5, SPITFIRE_IMPL 27040Sstevel@tonic-gate stxa %g0, [%g7]ASI_DC_INVAL 27050Sstevel@tonic-gate membar #Sync 27060Sstevel@tonic-gate ba,pt %xcc, 2f 27071772Sjl139090 nop 27080Sstevel@tonic-gate3: 27091772Sjl139090 bl,pt %icc, 2f 27101772Sjl139090 sethi %hi(dcache_line_mask), %g5 27110Sstevel@tonic-gate ld [%g5 + %lo(dcache_line_mask)], %g5 27120Sstevel@tonic-gate and %g6, %g5, %g5 27130Sstevel@tonic-gate stxa %g0, [%g5]ASI_DC_TAG 27140Sstevel@tonic-gate membar #Sync 27150Sstevel@tonic-gate2: 27160Sstevel@tonic-gate sta %g0, [%g7]ASI_MEM 27170Sstevel@tonic-gate SWITCH_GLOBALS ! back to mmu globals 27180Sstevel@tonic-gate ba,a,pt %xcc, sfmmu_mmu_trap ! handle page faults 27190Sstevel@tonic-gate1: 27200Sstevel@tonic-gate rdpr %tt, %g5 27210Sstevel@tonic-gate rdpr %tl, %g7 27220Sstevel@tonic-gate sub %g7, 1, %g6 27230Sstevel@tonic-gate wrpr %g6, %tl 27240Sstevel@tonic-gate rdpr %tt, %g6 27250Sstevel@tonic-gate wrpr %g7, %tl 27260Sstevel@tonic-gate and %g6, WTRAP_TTMASK, %g6 27270Sstevel@tonic-gate cmp %g6, WTRAP_TYPE 27280Sstevel@tonic-gate bne,a,pn %xcc, ptl1_panic 27290Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 27300Sstevel@tonic-gate rdpr %tpc, %g7 27310Sstevel@tonic-gate /* tpc should be in the trap table */ 27320Sstevel@tonic-gate set trap_table, %g6 27330Sstevel@tonic-gate cmp %g7, %g6 27340Sstevel@tonic-gate blt,a,pn %xcc, ptl1_panic 27350Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 27360Sstevel@tonic-gate set etrap_table, %g6 27370Sstevel@tonic-gate cmp %g7, %g6 27380Sstevel@tonic-gate bge,a,pn %xcc, ptl1_panic 27390Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 27400Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 27410Sstevel@tonic-gate move %icc, MMU_SFAR, %g6 27420Sstevel@tonic-gate movne %icc, MMU_TAG_ACCESS, %g6 27430Sstevel@tonic-gate ldxa [%g6]ASI_DMMU, %g6 27440Sstevel@tonic-gate andn %g7, WTRAP_ALIGN, %g7 /* 128 byte aligned */ 27450Sstevel@tonic-gate add %g7, WTRAP_FAULTOFF, %g7 27460Sstevel@tonic-gate wrpr %g0, %g7, %tnpc 27470Sstevel@tonic-gate done 27480Sstevel@tonic-gate SET_SIZE(mmu_trap_tl1) 27490Sstevel@tonic-gate 27500Sstevel@tonic-gate/* 27510Sstevel@tonic-gate * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers. These 27520Sstevel@tonic-gate * traps are valid only when kmdb is loaded. When the debugger is active, 27530Sstevel@tonic-gate * the code below is rewritten to transfer control to the appropriate 27540Sstevel@tonic-gate * debugger entry points. 27550Sstevel@tonic-gate */ 27560Sstevel@tonic-gate .global kmdb_trap 27570Sstevel@tonic-gate .align 8 27580Sstevel@tonic-gatekmdb_trap: 27590Sstevel@tonic-gate ba,a trap_table0 27600Sstevel@tonic-gate jmp %g1 + 0 27610Sstevel@tonic-gate nop 27620Sstevel@tonic-gate 27630Sstevel@tonic-gate .global kmdb_trap_tl1 27640Sstevel@tonic-gate .align 8 27650Sstevel@tonic-gatekmdb_trap_tl1: 27660Sstevel@tonic-gate ba,a trap_table0 27670Sstevel@tonic-gate jmp %g1 + 0 27680Sstevel@tonic-gate nop 27690Sstevel@tonic-gate 27700Sstevel@tonic-gate/* 27710Sstevel@tonic-gate * This entry is copied from OBP's trap table during boot. 27720Sstevel@tonic-gate */ 27730Sstevel@tonic-gate .global obp_bpt 27740Sstevel@tonic-gate .align 8 27750Sstevel@tonic-gateobp_bpt: 27760Sstevel@tonic-gate NOT 27770Sstevel@tonic-gate 27780Sstevel@tonic-gate/* 27790Sstevel@tonic-gate * if kernel, set PCONTEXT to 0 for debuggers 27800Sstevel@tonic-gate * if user, clear nucleus page sizes 27810Sstevel@tonic-gate */ 27820Sstevel@tonic-gate .global kctx_obp_bpt 27830Sstevel@tonic-gatekctx_obp_bpt: 27840Sstevel@tonic-gate set obp_bpt, %g2 27850Sstevel@tonic-gate1: 27865584Sjimand#ifndef _OPL 27870Sstevel@tonic-gate mov MMU_PCONTEXT, %g1 27880Sstevel@tonic-gate ldxa [%g1]ASI_DMMU, %g1 27890Sstevel@tonic-gate srlx %g1, CTXREG_NEXT_SHIFT, %g3 27900Sstevel@tonic-gate brz,pt %g3, 3f ! nucleus pgsz is 0, no problem 27910Sstevel@tonic-gate sllx %g3, CTXREG_NEXT_SHIFT, %g3 27920Sstevel@tonic-gate set CTXREG_CTX_MASK, %g4 ! check Pcontext 27930Sstevel@tonic-gate btst %g4, %g1 27940Sstevel@tonic-gate bz,a,pt %xcc, 2f 27950Sstevel@tonic-gate clr %g3 ! kernel: PCONTEXT=0 27960Sstevel@tonic-gate xor %g3, %g1, %g3 ! user: clr N_pgsz0/1 bits 27970Sstevel@tonic-gate2: 27980Sstevel@tonic-gate set DEMAP_ALL_TYPE, %g1 27990Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 28000Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 28010Sstevel@tonic-gate mov MMU_PCONTEXT, %g1 28020Sstevel@tonic-gate stxa %g3, [%g1]ASI_DMMU 28030Sstevel@tonic-gate membar #Sync 28040Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g1 28050Sstevel@tonic-gate flush %g1 ! flush required by immu 28065584Sjimand#endif /* _OPL */ 28070Sstevel@tonic-gate3: 28080Sstevel@tonic-gate jmp %g2 28090Sstevel@tonic-gate nop 28100Sstevel@tonic-gate 28110Sstevel@tonic-gate 28120Sstevel@tonic-gate#ifdef TRAPTRACE 28130Sstevel@tonic-gate/* 28140Sstevel@tonic-gate * TRAPTRACE support. 28150Sstevel@tonic-gate * labels here are branched to with "rd %pc, %g7" in the delay slot. 28160Sstevel@tonic-gate * Return is done by "jmp %g7 + 4". 28170Sstevel@tonic-gate */ 28180Sstevel@tonic-gate 28190Sstevel@tonic-gatetrace_gen: 28200Sstevel@tonic-gate TRACE_PTR(%g3, %g6) 2821*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) 28220Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 28230Sstevel@tonic-gate rdpr %tl, %g6 28240Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TL]%asi 28250Sstevel@tonic-gate rdpr %tt, %g6 28260Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi 28270Sstevel@tonic-gate rdpr %tstate, %g6 28280Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TSTATE]%asi 28290Sstevel@tonic-gate stna %sp, [%g3 + TRAP_ENT_SP]%asi 28300Sstevel@tonic-gate rdpr %tpc, %g6 28310Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_TPC]%asi 28320Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g5) 28330Sstevel@tonic-gate jmp %g7 + 4 28340Sstevel@tonic-gate nop 28350Sstevel@tonic-gate 28360Sstevel@tonic-gatetrace_win: 28370Sstevel@tonic-gate TRACE_WIN_INFO(0, %l0, %l1, %l2) 28380Sstevel@tonic-gate ! Keep the locals as clean as possible, caller cleans %l4 28390Sstevel@tonic-gate clr %l2 28400Sstevel@tonic-gate clr %l1 28410Sstevel@tonic-gate jmp %l4 + 4 28420Sstevel@tonic-gate clr %l0 28430Sstevel@tonic-gate 28440Sstevel@tonic-gate/* 28450Sstevel@tonic-gate * Trace a tsb hit 28460Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 28470Sstevel@tonic-gate * g2 = tag access register (in) 28480Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 28490Sstevel@tonic-gate * g5 = tsbe data (in) 28500Sstevel@tonic-gate * g6 = scratch (clobbered) 28510Sstevel@tonic-gate * g7 = pc we jumped here from (in) 28520Sstevel@tonic-gate */ 28530Sstevel@tonic-gate 28540Sstevel@tonic-gate ! Do not disturb %g5, it will be used after the trace 28550Sstevel@tonic-gate ALTENTRY(trace_tsbhit) 28560Sstevel@tonic-gate TRACE_TSBHIT(0) 28570Sstevel@tonic-gate jmp %g7 + 4 28580Sstevel@tonic-gate nop 28590Sstevel@tonic-gate 28600Sstevel@tonic-gate/* 28610Sstevel@tonic-gate * Trace a TSB miss 28620Sstevel@tonic-gate * 28630Sstevel@tonic-gate * g1 = tsb8k pointer (in) 28640Sstevel@tonic-gate * g2 = tag access register (in) 28650Sstevel@tonic-gate * g3 = tsb4m pointer (in) 28660Sstevel@tonic-gate * g4 = tsbe tag (in/clobbered) 28670Sstevel@tonic-gate * g5 - g6 = scratch (clobbered) 28680Sstevel@tonic-gate * g7 = pc we jumped here from (in) 28690Sstevel@tonic-gate */ 28700Sstevel@tonic-gate .global trace_tsbmiss 28710Sstevel@tonic-gatetrace_tsbmiss: 28720Sstevel@tonic-gate membar #Sync 28730Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 28740Sstevel@tonic-gate flush %g6 28750Sstevel@tonic-gate TRACE_PTR(%g5, %g6) 28760Sstevel@tonic-gate stxa %g2, [%g5 + TRAP_ENT_SP]%asi ! tag access 28770Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_F1]%asi ! tsb tag 2878*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) 2879*11172SHaik.Aftandilian@Sun.COM stxa %g6, [%g5 + TRAP_ENT_TICK]%asi 28800Sstevel@tonic-gate rdpr %tnpc, %g6 28810Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_F2]%asi 28820Sstevel@tonic-gate stna %g1, [%g5 + TRAP_ENT_F3]%asi ! tsb8k pointer 28830Sstevel@tonic-gate srlx %g1, 32, %g6 28840Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F4]%asi ! huh? 28850Sstevel@tonic-gate rdpr %tpc, %g6 28860Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_TPC]%asi 28870Sstevel@tonic-gate rdpr %tl, %g6 28880Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TL]%asi 28890Sstevel@tonic-gate rdpr %tt, %g6 28900Sstevel@tonic-gate or %g6, TT_MMU_MISS, %g4 28910Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 28920Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT 28930Sstevel@tonic-gate be,a %icc, 1f 28940Sstevel@tonic-gate ldxa [%g0]ASI_IMMU, %g6 28950Sstevel@tonic-gate ldxa [%g0]ASI_DMMU, %g6 28960Sstevel@tonic-gate1: stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! tag target 28970Sstevel@tonic-gate stxa %g3, [%g5 + TRAP_ENT_TR]%asi ! tsb4m pointer 28980Sstevel@tonic-gate TRACE_NEXT(%g5, %g4, %g6) 28990Sstevel@tonic-gate jmp %g7 + 4 29000Sstevel@tonic-gate nop 29010Sstevel@tonic-gate 29020Sstevel@tonic-gate/* 29030Sstevel@tonic-gate * g2 = tag access register (in) 29040Sstevel@tonic-gate * g3 = ctx number (in) 29050Sstevel@tonic-gate */ 29060Sstevel@tonic-gatetrace_dataprot: 29070Sstevel@tonic-gate membar #Sync 29080Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 29090Sstevel@tonic-gate flush %g6 29100Sstevel@tonic-gate TRACE_PTR(%g1, %g6) 2911*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g5) 29120Sstevel@tonic-gate stxa %g6, [%g1 + TRAP_ENT_TICK]%asi 29130Sstevel@tonic-gate rdpr %tpc, %g6 29140Sstevel@tonic-gate stna %g6, [%g1 + TRAP_ENT_TPC]%asi 29150Sstevel@tonic-gate rdpr %tstate, %g6 29160Sstevel@tonic-gate stxa %g6, [%g1 + TRAP_ENT_TSTATE]%asi 29170Sstevel@tonic-gate stxa %g2, [%g1 + TRAP_ENT_SP]%asi ! tag access reg 29180Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_TR]%asi 29190Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F1]%asi 29200Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F2]%asi 29210Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F3]%asi 29220Sstevel@tonic-gate stxa %g0, [%g1 + TRAP_ENT_F4]%asi 29230Sstevel@tonic-gate rdpr %tl, %g6 29240Sstevel@tonic-gate stha %g6, [%g1 + TRAP_ENT_TL]%asi 29250Sstevel@tonic-gate rdpr %tt, %g6 29260Sstevel@tonic-gate stha %g6, [%g1 + TRAP_ENT_TT]%asi 29270Sstevel@tonic-gate TRACE_NEXT(%g1, %g4, %g5) 29280Sstevel@tonic-gate jmp %g7 + 4 29290Sstevel@tonic-gate nop 29300Sstevel@tonic-gate 29310Sstevel@tonic-gate#endif /* TRAPTRACE */ 29320Sstevel@tonic-gate 29338803SJonathan.Haslam@Sun.COM .align 32 29348803SJonathan.Haslam@Sun.COM .global pil15_epilogue 29358803SJonathan.Haslam@Sun.COMpil15_epilogue: 29368803SJonathan.Haslam@Sun.COM ba pil_interrupt_common 29378803SJonathan.Haslam@Sun.COM nop 29388803SJonathan.Haslam@Sun.COM .align 32 29398803SJonathan.Haslam@Sun.COM 29400Sstevel@tonic-gate/* 29410Sstevel@tonic-gate * fast_trap_done, fast_trap_done_chk_intr: 29420Sstevel@tonic-gate * 29430Sstevel@tonic-gate * Due to the design of UltraSPARC pipeline, pending interrupts are not 29440Sstevel@tonic-gate * taken immediately after a RETRY or DONE instruction which causes IE to 29450Sstevel@tonic-gate * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed 29460Sstevel@tonic-gate * to execute first before taking any interrupts. If that instruction 29470Sstevel@tonic-gate * results in other traps, and if the corresponding trap handler runs 29480Sstevel@tonic-gate * entirely at TL=1 with interrupts disabled, then pending interrupts 29490Sstevel@tonic-gate * won't be taken until after yet another instruction following the %tpc 29500Sstevel@tonic-gate * or %tnpc. 29510Sstevel@tonic-gate * 29520Sstevel@tonic-gate * A malicious user program can use this feature to block out interrupts 29530Sstevel@tonic-gate * for extended durations, which can result in send_mondo_timeout kernel 29540Sstevel@tonic-gate * panic. 29550Sstevel@tonic-gate * 29560Sstevel@tonic-gate * This problem is addressed by servicing any pending interrupts via 29570Sstevel@tonic-gate * sys_trap before returning back to the user mode from a fast trap 29580Sstevel@tonic-gate * handler. The "done" instruction within a fast trap handler, which 29590Sstevel@tonic-gate * runs entirely at TL=1 with interrupts disabled, is replaced with the 29600Sstevel@tonic-gate * FAST_TRAP_DONE macro, which branches control to this fast_trap_done 29610Sstevel@tonic-gate * entry point. 29620Sstevel@tonic-gate * 29630Sstevel@tonic-gate * We check for any pending interrupts here and force a sys_trap to 29640Sstevel@tonic-gate * service those interrupts, if any. To minimize overhead, pending 29650Sstevel@tonic-gate * interrupts are checked if the %tpc happens to be at 16K boundary, 29660Sstevel@tonic-gate * which allows a malicious program to execute at most 4K consecutive 29670Sstevel@tonic-gate * instructions before we service any pending interrupts. If a worst 29680Sstevel@tonic-gate * case fast trap handler takes about 2 usec, then interrupts will be 29690Sstevel@tonic-gate * blocked for at most 8 msec, less than a clock tick. 29700Sstevel@tonic-gate * 29710Sstevel@tonic-gate * For the cases where we don't know if the %tpc will cross a 16K 29720Sstevel@tonic-gate * boundary, we can't use the above optimization and always process 29730Sstevel@tonic-gate * any pending interrupts via fast_frap_done_chk_intr entry point. 29740Sstevel@tonic-gate * 29750Sstevel@tonic-gate * Entry Conditions: 29760Sstevel@tonic-gate * %pstate am:0 priv:1 ie:0 29770Sstevel@tonic-gate * globals are AG (not normal globals) 29780Sstevel@tonic-gate */ 29790Sstevel@tonic-gate 29800Sstevel@tonic-gate .global fast_trap_done, fast_trap_done_chk_intr 29810Sstevel@tonic-gatefast_trap_done: 29820Sstevel@tonic-gate rdpr %tpc, %g5 29830Sstevel@tonic-gate sethi %hi(0xffffc000), %g6 ! 1's complement of 0x3fff 29840Sstevel@tonic-gate andncc %g5, %g6, %g0 ! check lower 14 bits of %tpc 29850Sstevel@tonic-gate bz,a,pn %icc, 1f ! branch if zero (lower 32 bits only) 29860Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 29870Sstevel@tonic-gate done 29880Sstevel@tonic-gate 29892712Snn35248 ALTENTRY(fast_trap_done_check_interrupts) 29900Sstevel@tonic-gatefast_trap_done_chk_intr: 29910Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 29920Sstevel@tonic-gate 29930Sstevel@tonic-gate1: rd SOFTINT, %g6 29940Sstevel@tonic-gate and %g5, IRSR_BUSY, %g5 29950Sstevel@tonic-gate orcc %g5, %g6, %g0 29960Sstevel@tonic-gate bnz,pn %xcc, 2f ! branch if any pending intr 29970Sstevel@tonic-gate nop 29980Sstevel@tonic-gate done 29990Sstevel@tonic-gate 30000Sstevel@tonic-gate2: 30010Sstevel@tonic-gate /* 30020Sstevel@tonic-gate * We get here if there are any pending interrupts. 30030Sstevel@tonic-gate * Adjust %tpc/%tnpc as we'll be resuming via "retry" 30040Sstevel@tonic-gate * instruction. 30050Sstevel@tonic-gate */ 30060Sstevel@tonic-gate rdpr %tnpc, %g5 30070Sstevel@tonic-gate wrpr %g0, %g5, %tpc 30080Sstevel@tonic-gate add %g5, 4, %g5 30090Sstevel@tonic-gate wrpr %g0, %g5, %tnpc 30100Sstevel@tonic-gate 30110Sstevel@tonic-gate /* 30120Sstevel@tonic-gate * Force a dummy sys_trap call so that interrupts can be serviced. 30130Sstevel@tonic-gate */ 30140Sstevel@tonic-gate set fast_trap_dummy_call, %g1 30150Sstevel@tonic-gate ba,pt %xcc, sys_trap 30160Sstevel@tonic-gate mov -1, %g4 30170Sstevel@tonic-gate 30180Sstevel@tonic-gatefast_trap_dummy_call: 30190Sstevel@tonic-gate retl 30200Sstevel@tonic-gate nop 30210Sstevel@tonic-gate 30222712Snn35248/* 30234141Sedp * Currently the brand syscall interposition code is not enabled by 30244141Sedp * default. Instead, when a branded zone is first booted the brand 30254141Sedp * infrastructure will patch the trap table so that the syscall 30264141Sedp * entry points are redirected to syscall_wrapper32 and syscall_wrapper 30274141Sedp * for ILP32 and LP64 syscalls respectively. this is done in 30284141Sedp * brand_plat_interposition_enable(). Note that the syscall wrappers 30294141Sedp * below do not collect any trap trace data since the syscall hot patch 30304141Sedp * points are reached after trap trace data has already been collected. 30312712Snn35248 */ 30322712Snn35248#define BRAND_CALLBACK(callback_id) \ 30334127Sedp CPU_ADDR(%g2, %g1) /* load CPU struct addr to %g2 */ ;\ 30344127Sedp ldn [%g2 + CPU_THREAD], %g3 /* load thread pointer */ ;\ 30354127Sedp ldn [%g3 + T_PROCP], %g3 /* get proc pointer */ ;\ 30364127Sedp ldn [%g3 + P_BRAND], %g3 /* get brand pointer */ ;\ 30374127Sedp brz %g3, 1f /* No brand? No callback. */ ;\ 30382712Snn35248 nop ;\ 30394127Sedp ldn [%g3 + B_MACHOPS], %g3 /* get machops list */ ;\ 30404127Sedp ldn [%g3 + (callback_id << 3)], %g3 ;\ 30414127Sedp brz %g3, 1f ;\ 30422712Snn35248 /* \ 30432712Snn35248 * This isn't pretty. We want a low-latency way for the callback \ 30442712Snn35248 * routine to decline to do anything. We just pass in an address \ 30452712Snn35248 * the routine can directly jmp back to, pretending that nothing \ 30462712Snn35248 * has happened. \ 30474127Sedp * \ 30484127Sedp * %g1: return address (where the brand handler jumps back to) \ 30494127Sedp * %g2: address of CPU structure \ 30504127Sedp * %g3: address of brand handler (where we will jump to) \ 30512712Snn35248 */ \ 30522712Snn35248 mov %pc, %g1 ;\ 30532712Snn35248 add %g1, 16, %g1 ;\ 30544127Sedp jmp %g3 ;\ 30552712Snn35248 nop ;\ 30562712Snn352481: 30572712Snn35248 30582712Snn35248 ENTRY_NP(syscall_wrapper32) 30592712Snn35248 BRAND_CALLBACK(BRAND_CB_SYSCALL32) 30604127Sedp SYSCALL_NOTT(syscall_trap32) 30612712Snn35248 SET_SIZE(syscall_wrapper32) 30622712Snn35248 30632712Snn35248 ENTRY_NP(syscall_wrapper) 30642712Snn35248 BRAND_CALLBACK(BRAND_CB_SYSCALL) 30654127Sedp SYSCALL_NOTT(syscall_trap) 30662712Snn35248 SET_SIZE(syscall_wrapper) 30672712Snn35248 30680Sstevel@tonic-gate#endif /* lint */ 3069