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 */ 212179Sahl 220Sstevel@tonic-gate/* 238803SJonathan.Haslam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate#if !defined(lint) 280Sstevel@tonic-gate#include "assym.h" 290Sstevel@tonic-gate#endif /* !lint */ 300Sstevel@tonic-gate#include <sys/asm_linkage.h> 310Sstevel@tonic-gate#include <sys/privregs.h> 320Sstevel@tonic-gate#include <sys/sun4asi.h> 330Sstevel@tonic-gate#include <sys/machasi.h> 340Sstevel@tonic-gate#include <sys/hypervisor_api.h> 350Sstevel@tonic-gate#include <sys/machtrap.h> 360Sstevel@tonic-gate#include <sys/machthread.h> 374127Sedp#include <sys/machbrand.h> 380Sstevel@tonic-gate#include <sys/pcb.h> 390Sstevel@tonic-gate#include <sys/pte.h> 400Sstevel@tonic-gate#include <sys/mmu.h> 410Sstevel@tonic-gate#include <sys/machpcb.h> 420Sstevel@tonic-gate#include <sys/async.h> 430Sstevel@tonic-gate#include <sys/intreg.h> 440Sstevel@tonic-gate#include <sys/scb.h> 450Sstevel@tonic-gate#include <sys/psr_compat.h> 460Sstevel@tonic-gate#include <sys/syscall.h> 470Sstevel@tonic-gate#include <sys/machparam.h> 480Sstevel@tonic-gate#include <sys/traptrace.h> 490Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 500Sstevel@tonic-gate#include <sys/archsystm.h> 510Sstevel@tonic-gate#include <sys/utrap.h> 520Sstevel@tonic-gate#include <sys/clock.h> 530Sstevel@tonic-gate#include <sys/intr.h> 540Sstevel@tonic-gate#include <sys/fpu/fpu_simulator.h> 550Sstevel@tonic-gate#include <vm/seg_spt.h> 560Sstevel@tonic-gate 570Sstevel@tonic-gate/* 580Sstevel@tonic-gate * WARNING: If you add a fast trap handler which can be invoked by a 590Sstevel@tonic-gate * non-privileged user, you may have to use the FAST_TRAP_DONE macro 600Sstevel@tonic-gate * instead of "done" instruction to return back to the user mode. See 610Sstevel@tonic-gate * comments for the "fast_trap_done" entry point for more information. 620Sstevel@tonic-gate * 630Sstevel@tonic-gate * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the 640Sstevel@tonic-gate * cases where you always want to process any pending interrupts before 650Sstevel@tonic-gate * returning back to the user mode. 660Sstevel@tonic-gate */ 670Sstevel@tonic-gate#define FAST_TRAP_DONE \ 680Sstevel@tonic-gate ba,a fast_trap_done 690Sstevel@tonic-gate 700Sstevel@tonic-gate#define FAST_TRAP_DONE_CHK_INTR \ 710Sstevel@tonic-gate ba,a fast_trap_done_chk_intr 720Sstevel@tonic-gate 730Sstevel@tonic-gate/* 740Sstevel@tonic-gate * SPARC V9 Trap Table 750Sstevel@tonic-gate * 760Sstevel@tonic-gate * Most of the trap handlers are made from common building 770Sstevel@tonic-gate * blocks, and some are instantiated multiple times within 780Sstevel@tonic-gate * the trap table. So, I build a bunch of macros, then 790Sstevel@tonic-gate * populate the table using only the macros. 800Sstevel@tonic-gate * 810Sstevel@tonic-gate * Many macros branch to sys_trap. Its calling convention is: 820Sstevel@tonic-gate * %g1 kernel trap handler 830Sstevel@tonic-gate * %g2, %g3 args for above 840Sstevel@tonic-gate * %g4 desire %pil 850Sstevel@tonic-gate */ 860Sstevel@tonic-gate 870Sstevel@tonic-gate#ifdef TRAPTRACE 880Sstevel@tonic-gate 890Sstevel@tonic-gate/* 900Sstevel@tonic-gate * Tracing macro. Adds two instructions if TRAPTRACE is defined. 910Sstevel@tonic-gate */ 920Sstevel@tonic-gate#define TT_TRACE(label) \ 930Sstevel@tonic-gate ba label ;\ 940Sstevel@tonic-gate rd %pc, %g7 950Sstevel@tonic-gate#define TT_TRACE_INS 2 960Sstevel@tonic-gate 970Sstevel@tonic-gate#define TT_TRACE_L(label) \ 980Sstevel@tonic-gate ba label ;\ 990Sstevel@tonic-gate rd %pc, %l4 ;\ 1000Sstevel@tonic-gate clr %l4 1010Sstevel@tonic-gate#define TT_TRACE_L_INS 3 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate#else 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate#define TT_TRACE(label) 1060Sstevel@tonic-gate#define TT_TRACE_INS 0 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate#define TT_TRACE_L(label) 1090Sstevel@tonic-gate#define TT_TRACE_L_INS 0 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate#endif 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate/* 1140Sstevel@tonic-gate * This first set are funneled to trap() with %tt as the type. 1150Sstevel@tonic-gate * Trap will then either panic or send the user a signal. 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate/* 1180Sstevel@tonic-gate * NOT is used for traps that just shouldn't happen. 1190Sstevel@tonic-gate * It comes in both single and quadruple flavors. 1200Sstevel@tonic-gate */ 1210Sstevel@tonic-gate#if !defined(lint) 1220Sstevel@tonic-gate .global trap 1230Sstevel@tonic-gate#endif /* !lint */ 1240Sstevel@tonic-gate#define NOT \ 1250Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1260Sstevel@tonic-gate set trap, %g1 ;\ 1270Sstevel@tonic-gate rdpr %tt, %g3 ;\ 1280Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1290Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1300Sstevel@tonic-gate .align 32 1310Sstevel@tonic-gate#define NOT4 NOT; NOT; NOT; NOT 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate#define NOTP \ 1340Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1350Sstevel@tonic-gate ba,pt %xcc, ptl1_panic ;\ 1360Sstevel@tonic-gate mov PTL1_BAD_TRAP, %g1 ;\ 1370Sstevel@tonic-gate .align 32 1380Sstevel@tonic-gate#define NOTP4 NOTP; NOTP; NOTP; NOTP 1390Sstevel@tonic-gate 1401991Sheppo 1410Sstevel@tonic-gate/* 1420Sstevel@tonic-gate * BAD is used for trap vectors we don't have a kernel 1430Sstevel@tonic-gate * handler for. 1440Sstevel@tonic-gate * It also comes in single and quadruple versions. 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate#define BAD NOT 1470Sstevel@tonic-gate#define BAD4 NOT4 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate#define DONE \ 1500Sstevel@tonic-gate done; \ 1510Sstevel@tonic-gate .align 32 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate/* 1540Sstevel@tonic-gate * TRAP vectors to the trap() function. 1550Sstevel@tonic-gate * It's main use is for user errors. 1560Sstevel@tonic-gate */ 1570Sstevel@tonic-gate#if !defined(lint) 1580Sstevel@tonic-gate .global trap 1590Sstevel@tonic-gate#endif /* !lint */ 1600Sstevel@tonic-gate#define TRAP(arg) \ 1610Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 1620Sstevel@tonic-gate set trap, %g1 ;\ 1630Sstevel@tonic-gate mov arg, %g3 ;\ 1640Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 1650Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1660Sstevel@tonic-gate .align 32 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate/* 1694141Sedp * SYSCALL is used for unsupported syscall interfaces (with 'which' 1704141Sedp * set to 'nosys') and legacy support of old SunOS 4.x syscalls (with 1714141Sedp * 'which' set to 'syscall_trap32'). 1724141Sedp * 1734141Sedp * The SYSCALL_TRAP* macros are used for syscall entry points. 1744141Sedp * SYSCALL_TRAP is used to support LP64 syscalls and SYSCALL_TRAP32 1754141Sedp * is used to support ILP32. Each macro can only be used once 1764141Sedp * since they each define a symbol. The symbols are used as hot patch 1774141Sedp * points by the brand infrastructure to dynamically enable and disable 1784141Sedp * brand syscall interposition. See the comments around BRAND_CALLBACK 1794141Sedp * and brand_plat_interposition_enable() for more information. 1800Sstevel@tonic-gate */ 1814127Sedp#define SYSCALL_NOTT(which) \ 1820Sstevel@tonic-gate set (which), %g1 ;\ 1836290Sjb145095 ba,pt %xcc, user_trap ;\ 1840Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 1850Sstevel@tonic-gate .align 32 1860Sstevel@tonic-gate 1874141Sedp#define SYSCALL(which) \ 1884141Sedp TT_TRACE(trace_gen) ;\ 1894141Sedp SYSCALL_NOTT(which) 1904141Sedp 1914141Sedp#define SYSCALL_TRAP32 \ 1924141Sedp TT_TRACE(trace_gen) ;\ 1934141Sedp ALTENTRY(syscall_trap32_patch_point) \ 1944141Sedp SYSCALL_NOTT(syscall_trap32) 1954141Sedp 1964141Sedp#define SYSCALL_TRAP \ 1974141Sedp TT_TRACE(trace_gen) ;\ 1984141Sedp ALTENTRY(syscall_trap_patch_point) \ 1994141Sedp SYSCALL_NOTT(syscall_trap) 2004141Sedp 2010Sstevel@tonic-gate/* 2020Sstevel@tonic-gate * GOTO just jumps to a label. 2030Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap. 2040Sstevel@tonic-gate */ 2050Sstevel@tonic-gate#define GOTO(label) \ 2060Sstevel@tonic-gate .global label ;\ 2070Sstevel@tonic-gate ba,a label ;\ 2080Sstevel@tonic-gate .empty ;\ 2090Sstevel@tonic-gate .align 32 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate/* 2120Sstevel@tonic-gate * GOTO_TT just jumps to a label. 2130Sstevel@tonic-gate * correctable ECC error traps at level 0 and 1 will use this macro. 2140Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap. 2150Sstevel@tonic-gate */ 2160Sstevel@tonic-gate#define GOTO_TT(label, ttlabel) \ 2170Sstevel@tonic-gate .global label ;\ 2180Sstevel@tonic-gate TT_TRACE(ttlabel) ;\ 2190Sstevel@tonic-gate ba,a label ;\ 2200Sstevel@tonic-gate .empty ;\ 2210Sstevel@tonic-gate .align 32 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate/* 2240Sstevel@tonic-gate * Privileged traps 2250Sstevel@tonic-gate * Takes breakpoint if privileged, calls trap() if not. 2260Sstevel@tonic-gate */ 2270Sstevel@tonic-gate#define PRIV(label) \ 2280Sstevel@tonic-gate rdpr %tstate, %g1 ;\ 2290Sstevel@tonic-gate btst TSTATE_PRIV, %g1 ;\ 2300Sstevel@tonic-gate bnz label ;\ 2310Sstevel@tonic-gate rdpr %tt, %g3 ;\ 2320Sstevel@tonic-gate set trap, %g1 ;\ 2330Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 2340Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2350Sstevel@tonic-gate .align 32 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate/* 2390Sstevel@tonic-gate * DTrace traps. 2400Sstevel@tonic-gate */ 2410Sstevel@tonic-gate#define DTRACE_PID \ 2420Sstevel@tonic-gate .global dtrace_pid_probe ;\ 2430Sstevel@tonic-gate set dtrace_pid_probe, %g1 ;\ 2440Sstevel@tonic-gate ba,pt %xcc, user_trap ;\ 2450Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 2460Sstevel@tonic-gate .align 32 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate#define DTRACE_RETURN \ 2490Sstevel@tonic-gate .global dtrace_return_probe ;\ 2500Sstevel@tonic-gate set dtrace_return_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/* 2560Sstevel@tonic-gate * REGISTER WINDOW MANAGEMENT MACROS 2570Sstevel@tonic-gate */ 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate/* 2600Sstevel@tonic-gate * various convenient units of padding 2610Sstevel@tonic-gate */ 2620Sstevel@tonic-gate#define SKIP(n) .skip 4*(n) 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate/* 2650Sstevel@tonic-gate * CLEAN_WINDOW is the simple handler for cleaning a register window. 2660Sstevel@tonic-gate */ 2670Sstevel@tonic-gate#define CLEAN_WINDOW \ 2680Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 2690Sstevel@tonic-gate rdpr %cleanwin, %l0; inc %l0; wrpr %l0, %cleanwin ;\ 2700Sstevel@tonic-gate clr %l0; clr %l1; clr %l2; clr %l3 ;\ 2710Sstevel@tonic-gate clr %l4; clr %l5; clr %l6; clr %l7 ;\ 2720Sstevel@tonic-gate clr %o0; clr %o1; clr %o2; clr %o3 ;\ 2730Sstevel@tonic-gate clr %o4; clr %o5; clr %o6; clr %o7 ;\ 2740Sstevel@tonic-gate retry; .align 128 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate#if !defined(lint) 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate/* 2790Sstevel@tonic-gate * If we get an unresolved tlb miss while in a window handler, the fault 2800Sstevel@tonic-gate * handler will resume execution at the last instruction of the window 2810Sstevel@tonic-gate * hander, instead of delivering the fault to the kernel. Spill handlers 2820Sstevel@tonic-gate * use this to spill windows into the wbuf. 2830Sstevel@tonic-gate * 2840Sstevel@tonic-gate * The mixed handler works by checking %sp, and branching to the correct 2850Sstevel@tonic-gate * handler. This is done by branching back to label 1: for 32b frames, 2860Sstevel@tonic-gate * or label 2: for 64b frames; which implies the handler order is: 32b, 2870Sstevel@tonic-gate * 64b, mixed. The 1: and 2: labels are offset into the routines to 2880Sstevel@tonic-gate * allow the branchs' delay slots to contain useful instructions. 2890Sstevel@tonic-gate */ 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate/* 2920Sstevel@tonic-gate * SPILL_32bit spills a 32-bit-wide kernel register window. It 2930Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the 2940Sstevel@tonic-gate * same. The stack pointer is required to be eight-byte aligned even 2950Sstevel@tonic-gate * though this code only needs it to be four-byte aligned. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate#define SPILL_32bit(tail) \ 2980Sstevel@tonic-gate srl %sp, 0, %sp ;\ 2990Sstevel@tonic-gate1: st %l0, [%sp + 0] ;\ 3000Sstevel@tonic-gate st %l1, [%sp + 4] ;\ 3010Sstevel@tonic-gate st %l2, [%sp + 8] ;\ 3020Sstevel@tonic-gate st %l3, [%sp + 12] ;\ 3030Sstevel@tonic-gate st %l4, [%sp + 16] ;\ 3040Sstevel@tonic-gate st %l5, [%sp + 20] ;\ 3050Sstevel@tonic-gate st %l6, [%sp + 24] ;\ 3060Sstevel@tonic-gate st %l7, [%sp + 28] ;\ 3070Sstevel@tonic-gate st %i0, [%sp + 32] ;\ 3080Sstevel@tonic-gate st %i1, [%sp + 36] ;\ 3090Sstevel@tonic-gate st %i2, [%sp + 40] ;\ 3100Sstevel@tonic-gate st %i3, [%sp + 44] ;\ 3110Sstevel@tonic-gate st %i4, [%sp + 48] ;\ 3120Sstevel@tonic-gate st %i5, [%sp + 52] ;\ 3130Sstevel@tonic-gate st %i6, [%sp + 56] ;\ 3140Sstevel@tonic-gate st %i7, [%sp + 60] ;\ 3150Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3160Sstevel@tonic-gate saved ;\ 3170Sstevel@tonic-gate retry ;\ 318303Sgirish SKIP(31-19-TT_TRACE_L_INS) ;\ 3190Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3200Sstevel@tonic-gate .empty 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate/* 3230Sstevel@tonic-gate * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit 3240Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 3250Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 3260Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte 3270Sstevel@tonic-gate * aligned. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate#define SPILL_32bit_asi(asi_num, tail) \ 3300Sstevel@tonic-gate srl %sp, 0, %sp ;\ 3310Sstevel@tonic-gate1: sta %l0, [%sp + %g0]asi_num ;\ 3320Sstevel@tonic-gate mov 4, %g1 ;\ 3330Sstevel@tonic-gate sta %l1, [%sp + %g1]asi_num ;\ 3340Sstevel@tonic-gate mov 8, %g2 ;\ 3350Sstevel@tonic-gate sta %l2, [%sp + %g2]asi_num ;\ 3360Sstevel@tonic-gate mov 12, %g3 ;\ 3370Sstevel@tonic-gate sta %l3, [%sp + %g3]asi_num ;\ 3380Sstevel@tonic-gate add %sp, 16, %g4 ;\ 3390Sstevel@tonic-gate sta %l4, [%g4 + %g0]asi_num ;\ 3400Sstevel@tonic-gate sta %l5, [%g4 + %g1]asi_num ;\ 3410Sstevel@tonic-gate sta %l6, [%g4 + %g2]asi_num ;\ 3420Sstevel@tonic-gate sta %l7, [%g4 + %g3]asi_num ;\ 3430Sstevel@tonic-gate add %g4, 16, %g4 ;\ 3440Sstevel@tonic-gate sta %i0, [%g4 + %g0]asi_num ;\ 3450Sstevel@tonic-gate sta %i1, [%g4 + %g1]asi_num ;\ 3460Sstevel@tonic-gate sta %i2, [%g4 + %g2]asi_num ;\ 3470Sstevel@tonic-gate sta %i3, [%g4 + %g3]asi_num ;\ 3480Sstevel@tonic-gate add %g4, 16, %g4 ;\ 3490Sstevel@tonic-gate sta %i4, [%g4 + %g0]asi_num ;\ 3500Sstevel@tonic-gate sta %i5, [%g4 + %g1]asi_num ;\ 3510Sstevel@tonic-gate sta %i6, [%g4 + %g2]asi_num ;\ 3520Sstevel@tonic-gate sta %i7, [%g4 + %g3]asi_num ;\ 3530Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 3540Sstevel@tonic-gate saved ;\ 3550Sstevel@tonic-gate retry ;\ 356303Sgirish SKIP(31-25-TT_TRACE_L_INS) ;\ 3570Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3580Sstevel@tonic-gate .empty 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate#define SPILL_32bit_tt1(asi_num, tail) \ 3610Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3620Sstevel@tonic-gate .empty ;\ 3630Sstevel@tonic-gate .align 128 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate/* 3670Sstevel@tonic-gate * FILL_32bit fills a 32-bit-wide kernel register window. It assumes 3680Sstevel@tonic-gate * that the kernel context and the nucleus context are the same. The 3690Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned even though this 3700Sstevel@tonic-gate * code only needs it to be four-byte aligned. 3710Sstevel@tonic-gate */ 3720Sstevel@tonic-gate#define FILL_32bit(tail) \ 3730Sstevel@tonic-gate srl %sp, 0, %sp ;\ 3740Sstevel@tonic-gate1: TT_TRACE_L(trace_win) ;\ 3750Sstevel@tonic-gate ld [%sp + 0], %l0 ;\ 3760Sstevel@tonic-gate ld [%sp + 4], %l1 ;\ 3770Sstevel@tonic-gate ld [%sp + 8], %l2 ;\ 3780Sstevel@tonic-gate ld [%sp + 12], %l3 ;\ 3790Sstevel@tonic-gate ld [%sp + 16], %l4 ;\ 3800Sstevel@tonic-gate ld [%sp + 20], %l5 ;\ 3810Sstevel@tonic-gate ld [%sp + 24], %l6 ;\ 3820Sstevel@tonic-gate ld [%sp + 28], %l7 ;\ 3830Sstevel@tonic-gate ld [%sp + 32], %i0 ;\ 3840Sstevel@tonic-gate ld [%sp + 36], %i1 ;\ 3850Sstevel@tonic-gate ld [%sp + 40], %i2 ;\ 3860Sstevel@tonic-gate ld [%sp + 44], %i3 ;\ 3870Sstevel@tonic-gate ld [%sp + 48], %i4 ;\ 3880Sstevel@tonic-gate ld [%sp + 52], %i5 ;\ 3890Sstevel@tonic-gate ld [%sp + 56], %i6 ;\ 3900Sstevel@tonic-gate ld [%sp + 60], %i7 ;\ 3910Sstevel@tonic-gate restored ;\ 3920Sstevel@tonic-gate retry ;\ 3930Sstevel@tonic-gate SKIP(31-19-TT_TRACE_L_INS) ;\ 3940Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 3950Sstevel@tonic-gate .empty 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate/* 3980Sstevel@tonic-gate * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit 3990Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 4000Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 4010Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte 4020Sstevel@tonic-gate * aligned. 4030Sstevel@tonic-gate */ 4040Sstevel@tonic-gate#define FILL_32bit_asi(asi_num, tail) \ 4050Sstevel@tonic-gate srl %sp, 0, %sp ;\ 4060Sstevel@tonic-gate1: TT_TRACE_L(trace_win) ;\ 4070Sstevel@tonic-gate mov 4, %g1 ;\ 4080Sstevel@tonic-gate lda [%sp + %g0]asi_num, %l0 ;\ 4090Sstevel@tonic-gate mov 8, %g2 ;\ 4100Sstevel@tonic-gate lda [%sp + %g1]asi_num, %l1 ;\ 4110Sstevel@tonic-gate mov 12, %g3 ;\ 4120Sstevel@tonic-gate lda [%sp + %g2]asi_num, %l2 ;\ 4130Sstevel@tonic-gate lda [%sp + %g3]asi_num, %l3 ;\ 4140Sstevel@tonic-gate add %sp, 16, %g4 ;\ 4150Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %l4 ;\ 4160Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %l5 ;\ 4170Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %l6 ;\ 4180Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %l7 ;\ 4190Sstevel@tonic-gate add %g4, 16, %g4 ;\ 4200Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %i0 ;\ 4210Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %i1 ;\ 4220Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %i2 ;\ 4230Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %i3 ;\ 4240Sstevel@tonic-gate add %g4, 16, %g4 ;\ 4250Sstevel@tonic-gate lda [%g4 + %g0]asi_num, %i4 ;\ 4260Sstevel@tonic-gate lda [%g4 + %g1]asi_num, %i5 ;\ 4270Sstevel@tonic-gate lda [%g4 + %g2]asi_num, %i6 ;\ 4280Sstevel@tonic-gate lda [%g4 + %g3]asi_num, %i7 ;\ 4290Sstevel@tonic-gate restored ;\ 4300Sstevel@tonic-gate retry ;\ 4310Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 4320Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 4330Sstevel@tonic-gate .empty 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate/* 4370Sstevel@tonic-gate * SPILL_64bit spills a 64-bit-wide kernel register window. It 4380Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the 4390Sstevel@tonic-gate * same. The stack pointer is required to be eight-byte aligned. 4400Sstevel@tonic-gate */ 4410Sstevel@tonic-gate#define SPILL_64bit(tail) \ 4420Sstevel@tonic-gate2: stx %l0, [%sp + V9BIAS64 + 0] ;\ 4430Sstevel@tonic-gate stx %l1, [%sp + V9BIAS64 + 8] ;\ 4440Sstevel@tonic-gate stx %l2, [%sp + V9BIAS64 + 16] ;\ 4450Sstevel@tonic-gate stx %l3, [%sp + V9BIAS64 + 24] ;\ 4460Sstevel@tonic-gate stx %l4, [%sp + V9BIAS64 + 32] ;\ 4470Sstevel@tonic-gate stx %l5, [%sp + V9BIAS64 + 40] ;\ 4480Sstevel@tonic-gate stx %l6, [%sp + V9BIAS64 + 48] ;\ 4490Sstevel@tonic-gate stx %l7, [%sp + V9BIAS64 + 56] ;\ 4500Sstevel@tonic-gate stx %i0, [%sp + V9BIAS64 + 64] ;\ 4510Sstevel@tonic-gate stx %i1, [%sp + V9BIAS64 + 72] ;\ 4520Sstevel@tonic-gate stx %i2, [%sp + V9BIAS64 + 80] ;\ 4530Sstevel@tonic-gate stx %i3, [%sp + V9BIAS64 + 88] ;\ 4540Sstevel@tonic-gate stx %i4, [%sp + V9BIAS64 + 96] ;\ 4550Sstevel@tonic-gate stx %i5, [%sp + V9BIAS64 + 104] ;\ 4560Sstevel@tonic-gate stx %i6, [%sp + V9BIAS64 + 112] ;\ 4570Sstevel@tonic-gate stx %i7, [%sp + V9BIAS64 + 120] ;\ 4580Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 4590Sstevel@tonic-gate saved ;\ 4600Sstevel@tonic-gate retry ;\ 461303Sgirish SKIP(31-18-TT_TRACE_L_INS) ;\ 4620Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 4630Sstevel@tonic-gate .empty 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate#define SPILL_64bit_ktt1(tail) \ 4660Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 4670Sstevel@tonic-gate .empty ;\ 4680Sstevel@tonic-gate .align 128 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate#define SPILL_mixed_ktt1(tail) \ 4710Sstevel@tonic-gate btst 1, %sp ;\ 4720Sstevel@tonic-gate bz,a,pt %xcc, fault_32bit_/**/tail ;\ 4730Sstevel@tonic-gate srl %sp, 0, %sp ;\ 4740Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 4750Sstevel@tonic-gate .empty ;\ 4760Sstevel@tonic-gate .align 128 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate/* 4790Sstevel@tonic-gate * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit 4800Sstevel@tonic-gate * wide address space via the designated asi. It is used to spill 4810Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 4820Sstevel@tonic-gate * aligned. 4830Sstevel@tonic-gate */ 4840Sstevel@tonic-gate#define SPILL_64bit_asi(asi_num, tail) \ 4850Sstevel@tonic-gate mov 0 + V9BIAS64, %g1 ;\ 4860Sstevel@tonic-gate2: stxa %l0, [%sp + %g1]asi_num ;\ 4870Sstevel@tonic-gate mov 8 + V9BIAS64, %g2 ;\ 4880Sstevel@tonic-gate stxa %l1, [%sp + %g2]asi_num ;\ 4890Sstevel@tonic-gate mov 16 + V9BIAS64, %g3 ;\ 4900Sstevel@tonic-gate stxa %l2, [%sp + %g3]asi_num ;\ 4910Sstevel@tonic-gate mov 24 + V9BIAS64, %g4 ;\ 4920Sstevel@tonic-gate stxa %l3, [%sp + %g4]asi_num ;\ 4930Sstevel@tonic-gate add %sp, 32, %g5 ;\ 4940Sstevel@tonic-gate stxa %l4, [%g5 + %g1]asi_num ;\ 4950Sstevel@tonic-gate stxa %l5, [%g5 + %g2]asi_num ;\ 4960Sstevel@tonic-gate stxa %l6, [%g5 + %g3]asi_num ;\ 4970Sstevel@tonic-gate stxa %l7, [%g5 + %g4]asi_num ;\ 4980Sstevel@tonic-gate add %g5, 32, %g5 ;\ 4990Sstevel@tonic-gate stxa %i0, [%g5 + %g1]asi_num ;\ 5000Sstevel@tonic-gate stxa %i1, [%g5 + %g2]asi_num ;\ 5010Sstevel@tonic-gate stxa %i2, [%g5 + %g3]asi_num ;\ 5020Sstevel@tonic-gate stxa %i3, [%g5 + %g4]asi_num ;\ 5030Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5040Sstevel@tonic-gate stxa %i4, [%g5 + %g1]asi_num ;\ 5050Sstevel@tonic-gate stxa %i5, [%g5 + %g2]asi_num ;\ 5060Sstevel@tonic-gate stxa %i6, [%g5 + %g3]asi_num ;\ 5070Sstevel@tonic-gate stxa %i7, [%g5 + %g4]asi_num ;\ 5080Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 5090Sstevel@tonic-gate saved ;\ 5100Sstevel@tonic-gate retry ;\ 511303Sgirish SKIP(31-25-TT_TRACE_L_INS) ;\ 5120Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5130Sstevel@tonic-gate .empty 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate#define SPILL_64bit_tt1(asi_num, tail) \ 5160Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5170Sstevel@tonic-gate .empty ;\ 5180Sstevel@tonic-gate .align 128 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate/* 5210Sstevel@tonic-gate * FILL_64bit fills a 64-bit-wide kernel register window. It assumes 5220Sstevel@tonic-gate * that the kernel context and the nucleus context are the same. The 5230Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned. 5240Sstevel@tonic-gate */ 5250Sstevel@tonic-gate#define FILL_64bit(tail) \ 5260Sstevel@tonic-gate2: TT_TRACE_L(trace_win) ;\ 5270Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 0], %l0 ;\ 5280Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 8], %l1 ;\ 5290Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 16], %l2 ;\ 5300Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 24], %l3 ;\ 5310Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 32], %l4 ;\ 5320Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 40], %l5 ;\ 5330Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 48], %l6 ;\ 5340Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 56], %l7 ;\ 5350Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 64], %i0 ;\ 5360Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 72], %i1 ;\ 5370Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 80], %i2 ;\ 5380Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 88], %i3 ;\ 5390Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 96], %i4 ;\ 5400Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 104], %i5 ;\ 5410Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 112], %i6 ;\ 5420Sstevel@tonic-gate ldx [%sp + V9BIAS64 + 120], %i7 ;\ 5430Sstevel@tonic-gate restored ;\ 5440Sstevel@tonic-gate retry ;\ 5450Sstevel@tonic-gate SKIP(31-18-TT_TRACE_L_INS) ;\ 5460Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5470Sstevel@tonic-gate .empty 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate/* 5500Sstevel@tonic-gate * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit 5510Sstevel@tonic-gate * wide address space via the designated asi. It is used to fill 5520Sstevel@tonic-gate * non-kernel windows. The stack pointer is required to be eight-byte 5534127Sedp * aligned. 5540Sstevel@tonic-gate */ 5550Sstevel@tonic-gate#define FILL_64bit_asi(asi_num, tail) \ 5560Sstevel@tonic-gate mov V9BIAS64 + 0, %g1 ;\ 5570Sstevel@tonic-gate2: TT_TRACE_L(trace_win) ;\ 5580Sstevel@tonic-gate ldxa [%sp + %g1]asi_num, %l0 ;\ 5590Sstevel@tonic-gate mov V9BIAS64 + 8, %g2 ;\ 5600Sstevel@tonic-gate ldxa [%sp + %g2]asi_num, %l1 ;\ 5610Sstevel@tonic-gate mov V9BIAS64 + 16, %g3 ;\ 5620Sstevel@tonic-gate ldxa [%sp + %g3]asi_num, %l2 ;\ 5630Sstevel@tonic-gate mov V9BIAS64 + 24, %g4 ;\ 5640Sstevel@tonic-gate ldxa [%sp + %g4]asi_num, %l3 ;\ 5650Sstevel@tonic-gate add %sp, 32, %g5 ;\ 5660Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %l4 ;\ 5670Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %l5 ;\ 5680Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %l6 ;\ 5690Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %l7 ;\ 5700Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5710Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %i0 ;\ 5720Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %i1 ;\ 5730Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %i2 ;\ 5740Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %i3 ;\ 5750Sstevel@tonic-gate add %g5, 32, %g5 ;\ 5760Sstevel@tonic-gate ldxa [%g5 + %g1]asi_num, %i4 ;\ 5770Sstevel@tonic-gate ldxa [%g5 + %g2]asi_num, %i5 ;\ 5780Sstevel@tonic-gate ldxa [%g5 + %g3]asi_num, %i6 ;\ 5790Sstevel@tonic-gate ldxa [%g5 + %g4]asi_num, %i7 ;\ 5800Sstevel@tonic-gate restored ;\ 5810Sstevel@tonic-gate retry ;\ 5820Sstevel@tonic-gate SKIP(31-25-TT_TRACE_L_INS) ;\ 5830Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 5840Sstevel@tonic-gate .empty 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate#endif /* !lint */ 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate/* 5900Sstevel@tonic-gate * SPILL_mixed spills either size window, depending on 5910Sstevel@tonic-gate * whether %sp is even or odd, to a 32-bit address space. 5920Sstevel@tonic-gate * This may only be used in conjunction with SPILL_32bit/ 5930Sstevel@tonic-gate * FILL_64bit. 5940Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd. 5950Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel. 5960Sstevel@tonic-gate */ 5970Sstevel@tonic-gate#define SPILL_mixed \ 5980Sstevel@tonic-gate btst 1, %sp ;\ 5990Sstevel@tonic-gate bz,a,pt %xcc, 1b ;\ 6000Sstevel@tonic-gate srl %sp, 0, %sp ;\ 6010Sstevel@tonic-gate ba,pt %xcc, 2b ;\ 6020Sstevel@tonic-gate nop ;\ 6030Sstevel@tonic-gate .align 128 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate/* 6060Sstevel@tonic-gate * FILL_mixed(ASI) fills either size window, depending on 6070Sstevel@tonic-gate * whether %sp is even or odd, from a 32-bit address space. 6080Sstevel@tonic-gate * This may only be used in conjunction with FILL_32bit/ 6090Sstevel@tonic-gate * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be 6100Sstevel@tonic-gate * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular 6110Sstevel@tonic-gate * attention should be paid to the instructions that belong 6120Sstevel@tonic-gate * in the delay slots of the branches depending on the type 6130Sstevel@tonic-gate * of fill handler being branched to. 6140Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd. 6150Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel. 6160Sstevel@tonic-gate */ 6170Sstevel@tonic-gate#define FILL_mixed \ 6180Sstevel@tonic-gate btst 1, %sp ;\ 6190Sstevel@tonic-gate bz,a,pt %xcc, 1b ;\ 6200Sstevel@tonic-gate srl %sp, 0, %sp ;\ 6210Sstevel@tonic-gate ba,pt %xcc, 2b ;\ 6220Sstevel@tonic-gate nop ;\ 6230Sstevel@tonic-gate .align 128 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate/* 6270Sstevel@tonic-gate * SPILL_32clean/SPILL_64clean spill 32-bit and 64-bit register windows, 6280Sstevel@tonic-gate * respectively, into the address space via the designated asi. The 6290Sstevel@tonic-gate * unbiased stack pointer is required to be eight-byte aligned (even for 6300Sstevel@tonic-gate * the 32-bit case even though this code does not require such strict 6310Sstevel@tonic-gate * alignment). 6320Sstevel@tonic-gate * 6330Sstevel@tonic-gate * With SPARC v9 the spill trap takes precedence over the cleanwin trap 6340Sstevel@tonic-gate * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save 6350Sstevel@tonic-gate * will cause cwp + 2 to be spilled but will not clean cwp + 1. That 6360Sstevel@tonic-gate * window may contain kernel data so in user_rtt we set wstate to call 6370Sstevel@tonic-gate * these spill handlers on the first user spill trap. These handler then 6380Sstevel@tonic-gate * spill the appropriate window but also back up a window and clean the 6390Sstevel@tonic-gate * window that didn't get a cleanwin trap. 6400Sstevel@tonic-gate */ 6410Sstevel@tonic-gate#define SPILL_32clean(asi_num, tail) \ 6420Sstevel@tonic-gate srl %sp, 0, %sp ;\ 6430Sstevel@tonic-gate sta %l0, [%sp + %g0]asi_num ;\ 6440Sstevel@tonic-gate mov 4, %g1 ;\ 6450Sstevel@tonic-gate sta %l1, [%sp + %g1]asi_num ;\ 6460Sstevel@tonic-gate mov 8, %g2 ;\ 6470Sstevel@tonic-gate sta %l2, [%sp + %g2]asi_num ;\ 6480Sstevel@tonic-gate mov 12, %g3 ;\ 6490Sstevel@tonic-gate sta %l3, [%sp + %g3]asi_num ;\ 6500Sstevel@tonic-gate add %sp, 16, %g4 ;\ 6510Sstevel@tonic-gate sta %l4, [%g4 + %g0]asi_num ;\ 6520Sstevel@tonic-gate sta %l5, [%g4 + %g1]asi_num ;\ 6530Sstevel@tonic-gate sta %l6, [%g4 + %g2]asi_num ;\ 6540Sstevel@tonic-gate sta %l7, [%g4 + %g3]asi_num ;\ 6550Sstevel@tonic-gate add %g4, 16, %g4 ;\ 6560Sstevel@tonic-gate sta %i0, [%g4 + %g0]asi_num ;\ 6570Sstevel@tonic-gate sta %i1, [%g4 + %g1]asi_num ;\ 6580Sstevel@tonic-gate sta %i2, [%g4 + %g2]asi_num ;\ 6590Sstevel@tonic-gate sta %i3, [%g4 + %g3]asi_num ;\ 6600Sstevel@tonic-gate add %g4, 16, %g4 ;\ 6610Sstevel@tonic-gate sta %i4, [%g4 + %g0]asi_num ;\ 6620Sstevel@tonic-gate sta %i5, [%g4 + %g1]asi_num ;\ 6630Sstevel@tonic-gate sta %i6, [%g4 + %g2]asi_num ;\ 6640Sstevel@tonic-gate sta %i7, [%g4 + %g3]asi_num ;\ 6650Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 6660Sstevel@tonic-gate b .spill_clean ;\ 6670Sstevel@tonic-gate mov WSTATE_USER32, %g7 ;\ 668303Sgirish SKIP(31-25-TT_TRACE_L_INS) ;\ 6690Sstevel@tonic-gate ba,a,pt %xcc, fault_32bit_/**/tail ;\ 6700Sstevel@tonic-gate .empty 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate#define SPILL_64clean(asi_num, tail) \ 6730Sstevel@tonic-gate mov 0 + V9BIAS64, %g1 ;\ 6740Sstevel@tonic-gate stxa %l0, [%sp + %g1]asi_num ;\ 6750Sstevel@tonic-gate mov 8 + V9BIAS64, %g2 ;\ 6760Sstevel@tonic-gate stxa %l1, [%sp + %g2]asi_num ;\ 6770Sstevel@tonic-gate mov 16 + V9BIAS64, %g3 ;\ 6780Sstevel@tonic-gate stxa %l2, [%sp + %g3]asi_num ;\ 6790Sstevel@tonic-gate mov 24 + V9BIAS64, %g4 ;\ 6800Sstevel@tonic-gate stxa %l3, [%sp + %g4]asi_num ;\ 6810Sstevel@tonic-gate add %sp, 32, %g5 ;\ 6820Sstevel@tonic-gate stxa %l4, [%g5 + %g1]asi_num ;\ 6830Sstevel@tonic-gate stxa %l5, [%g5 + %g2]asi_num ;\ 6840Sstevel@tonic-gate stxa %l6, [%g5 + %g3]asi_num ;\ 6850Sstevel@tonic-gate stxa %l7, [%g5 + %g4]asi_num ;\ 6860Sstevel@tonic-gate add %g5, 32, %g5 ;\ 6870Sstevel@tonic-gate stxa %i0, [%g5 + %g1]asi_num ;\ 6880Sstevel@tonic-gate stxa %i1, [%g5 + %g2]asi_num ;\ 6890Sstevel@tonic-gate stxa %i2, [%g5 + %g3]asi_num ;\ 6900Sstevel@tonic-gate stxa %i3, [%g5 + %g4]asi_num ;\ 6910Sstevel@tonic-gate add %g5, 32, %g5 ;\ 6920Sstevel@tonic-gate stxa %i4, [%g5 + %g1]asi_num ;\ 6930Sstevel@tonic-gate stxa %i5, [%g5 + %g2]asi_num ;\ 6940Sstevel@tonic-gate stxa %i6, [%g5 + %g3]asi_num ;\ 6950Sstevel@tonic-gate stxa %i7, [%g5 + %g4]asi_num ;\ 6960Sstevel@tonic-gate TT_TRACE_L(trace_win) ;\ 6970Sstevel@tonic-gate b .spill_clean ;\ 6980Sstevel@tonic-gate mov WSTATE_USER64, %g7 ;\ 699303Sgirish SKIP(31-25-TT_TRACE_L_INS) ;\ 7000Sstevel@tonic-gate ba,a,pt %xcc, fault_64bit_/**/tail ;\ 7010Sstevel@tonic-gate .empty 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate/* 7050Sstevel@tonic-gate * Floating point disabled. 7060Sstevel@tonic-gate */ 7070Sstevel@tonic-gate#define FP_DISABLED_TRAP \ 7080Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7090Sstevel@tonic-gate ba,pt %xcc,.fp_disabled ;\ 7100Sstevel@tonic-gate nop ;\ 7110Sstevel@tonic-gate .align 32 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate/* 7140Sstevel@tonic-gate * Floating point exceptions. 7150Sstevel@tonic-gate */ 7160Sstevel@tonic-gate#define FP_IEEE_TRAP \ 7170Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7180Sstevel@tonic-gate ba,pt %xcc,.fp_ieee_exception ;\ 7190Sstevel@tonic-gate nop ;\ 7200Sstevel@tonic-gate .align 32 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate#define FP_TRAP \ 7230Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7240Sstevel@tonic-gate ba,pt %xcc,.fp_exception ;\ 7250Sstevel@tonic-gate nop ;\ 7260Sstevel@tonic-gate .align 32 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate#if !defined(lint) 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate/* 7310Sstevel@tonic-gate * ECACHE_ECC error traps at level 0 and level 1 7320Sstevel@tonic-gate */ 7330Sstevel@tonic-gate#define ECACHE_ECC(table_name) \ 7340Sstevel@tonic-gate .global table_name ;\ 7350Sstevel@tonic-gatetable_name: ;\ 7360Sstevel@tonic-gate membar #Sync ;\ 7370Sstevel@tonic-gate set trap, %g1 ;\ 7380Sstevel@tonic-gate rdpr %tt, %g3 ;\ 7390Sstevel@tonic-gate ba,pt %xcc, sys_trap ;\ 7400Sstevel@tonic-gate sub %g0, 1, %g4 ;\ 7410Sstevel@tonic-gate .align 32 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate#endif /* !lint */ 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate/* 7460Sstevel@tonic-gate * illegal instruction trap 7470Sstevel@tonic-gate */ 7480Sstevel@tonic-gate#define ILLTRAP_INSTR \ 7490Sstevel@tonic-gate membar #Sync ;\ 7500Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7510Sstevel@tonic-gate or %g0, P_UTRAP4, %g2 ;\ 7520Sstevel@tonic-gate or %g0, T_UNIMP_INSTR, %g3 ;\ 7530Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 7540Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 7550Sstevel@tonic-gate nop ;\ 7560Sstevel@tonic-gate .align 32 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate/* 7590Sstevel@tonic-gate * tag overflow trap 7600Sstevel@tonic-gate */ 7610Sstevel@tonic-gate#define TAG_OVERFLOW \ 7620Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7630Sstevel@tonic-gate or %g0, P_UTRAP10, %g2 ;\ 7640Sstevel@tonic-gate or %g0, T_TAG_OVERFLOW, %g3 ;\ 7650Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 7660Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 7670Sstevel@tonic-gate nop ;\ 7680Sstevel@tonic-gate .align 32 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate/* 7710Sstevel@tonic-gate * divide by zero trap 7720Sstevel@tonic-gate */ 7730Sstevel@tonic-gate#define DIV_BY_ZERO \ 7740Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7750Sstevel@tonic-gate or %g0, P_UTRAP11, %g2 ;\ 7760Sstevel@tonic-gate or %g0, T_IDIV0, %g3 ;\ 7770Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 7780Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 7790Sstevel@tonic-gate nop ;\ 7800Sstevel@tonic-gate .align 32 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate/* 7830Sstevel@tonic-gate * trap instruction for V9 user trap handlers 7840Sstevel@tonic-gate */ 7850Sstevel@tonic-gate#define TRAP_INSTR \ 7860Sstevel@tonic-gate TT_TRACE(trace_gen) ;\ 7870Sstevel@tonic-gate or %g0, T_SOFTWARE_TRAP, %g3 ;\ 7880Sstevel@tonic-gate sethi %hi(.check_v9utrap), %g4 ;\ 7890Sstevel@tonic-gate jmp %g4 + %lo(.check_v9utrap) ;\ 7900Sstevel@tonic-gate nop ;\ 7910Sstevel@tonic-gate .align 32 7920Sstevel@tonic-gate#define TRP4 TRAP_INSTR; TRAP_INSTR; TRAP_INSTR; TRAP_INSTR 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate/* 7950Sstevel@tonic-gate * LEVEL_INTERRUPT is for level N interrupts. 7960Sstevel@tonic-gate * VECTOR_INTERRUPT is for the vector trap. 7970Sstevel@tonic-gate */ 7980Sstevel@tonic-gate#define LEVEL_INTERRUPT(level) \ 7990Sstevel@tonic-gate .global tt_pil/**/level ;\ 8000Sstevel@tonic-gatett_pil/**/level: ;\ 8010Sstevel@tonic-gate ba,pt %xcc, pil_interrupt ;\ 8020Sstevel@tonic-gate mov level, %g4 ;\ 8030Sstevel@tonic-gate .align 32 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate#define LEVEL14_INTERRUPT \ 8060Sstevel@tonic-gate ba pil14_interrupt ;\ 8070Sstevel@tonic-gate mov PIL_14, %g4 ;\ 8080Sstevel@tonic-gate .align 32 8090Sstevel@tonic-gate 8108803SJonathan.Haslam@Sun.COM#define LEVEL15_INTERRUPT \ 8118803SJonathan.Haslam@Sun.COM ba pil15_interrupt ;\ 8128803SJonathan.Haslam@Sun.COM mov PIL_15, %g4 ;\ 8138803SJonathan.Haslam@Sun.COM .align 32 8148803SJonathan.Haslam@Sun.COM 8150Sstevel@tonic-gate#define CPU_MONDO \ 8160Sstevel@tonic-gate ba,a,pt %xcc, cpu_mondo ;\ 8170Sstevel@tonic-gate .align 32 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate#define DEV_MONDO \ 8200Sstevel@tonic-gate ba,a,pt %xcc, dev_mondo ;\ 8210Sstevel@tonic-gate .align 32 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate/* 8241991Sheppo * We take over the rtba after we set our trap table and 8251991Sheppo * fault status area. The watchdog reset trap is now handled by the OS. 8261991Sheppo */ 8271991Sheppo#define WATCHDOG_RESET \ 8281991Sheppo mov PTL1_BAD_WATCHDOG, %g1 ;\ 8291991Sheppo ba,a,pt %xcc, .watchdog_trap ;\ 8301991Sheppo .align 32 8311991Sheppo 8321991Sheppo/* 8331991Sheppo * RED is for traps that use the red mode handler. 8341991Sheppo * We should never see these either. 8351991Sheppo */ 8361991Sheppo#define RED \ 8371991Sheppo mov PTL1_BAD_RED, %g1 ;\ 8381991Sheppo ba,a,pt %xcc, .watchdog_trap ;\ 8391991Sheppo .align 32 8401991Sheppo 8414127Sedp 8421991Sheppo/* 8430Sstevel@tonic-gate * MMU Trap Handlers. 8440Sstevel@tonic-gate */ 8450Sstevel@tonic-gate 846526Sarao/* 847526Sarao * synthesize for trap(): SFSR in %g3 848526Sarao */ 8498071SDave.Plauger@Sun.COM#define IMMU_EXCEPTION \ 8508071SDave.Plauger@Sun.COM MMU_FAULT_STATUS_AREA(%g3) ;\ 8518071SDave.Plauger@Sun.COM rdpr %tpc, %g2 ;\ 8528071SDave.Plauger@Sun.COM ldx [%g3 + MMFSA_I_TYPE], %g1 ;\ 8538071SDave.Plauger@Sun.COM ldx [%g3 + MMFSA_I_CTX], %g3 ;\ 8548071SDave.Plauger@Sun.COM sllx %g3, SFSR_CTX_SHIFT, %g3 ;\ 8558071SDave.Plauger@Sun.COM or %g3, %g1, %g3 ;\ 8568071SDave.Plauger@Sun.COM ba,pt %xcc, .mmu_exception_end ;\ 8578071SDave.Plauger@Sun.COM mov T_INSTR_EXCEPTION, %g1 ;\ 8580Sstevel@tonic-gate .align 32 8590Sstevel@tonic-gate 860526Sarao/* 861526Sarao * synthesize for trap(): TAG_ACCESS in %g2, SFSR in %g3 862526Sarao */ 8630Sstevel@tonic-gate#define DMMU_EXCEPTION \ 864526Sarao ba,a,pt %xcc, .dmmu_exception ;\ 8650Sstevel@tonic-gate .align 32 8660Sstevel@tonic-gate 867526Sarao/* 868526Sarao * synthesize for trap(): SFAR in %g2, SFSR in %g3 869526Sarao */ 8700Sstevel@tonic-gate#define DMMU_EXC_AG_PRIV \ 8710Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g3) ;\ 8720Sstevel@tonic-gate ldx [%g3 + MMFSA_D_ADDR], %g2 ;\ 8730Sstevel@tonic-gate /* Fault type not available in MMU fault status area */ ;\ 8740Sstevel@tonic-gate mov MMFSA_F_PRVACT, %g1 ;\ 8750Sstevel@tonic-gate ldx [%g3 + MMFSA_D_CTX], %g3 ;\ 8760Sstevel@tonic-gate sllx %g3, SFSR_CTX_SHIFT, %g3 ;\ 8770Sstevel@tonic-gate ba,pt %xcc, .mmu_priv_exception ;\ 8780Sstevel@tonic-gate or %g3, %g1, %g3 ;\ 8790Sstevel@tonic-gate .align 32 8800Sstevel@tonic-gate 881526Sarao/* 882526Sarao * synthesize for trap(): SFAR in %g2, SFSR in %g3 883526Sarao */ 8840Sstevel@tonic-gate#define DMMU_EXC_AG_NOT_ALIGNED \ 8850Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g3) ;\ 8860Sstevel@tonic-gate ldx [%g3 + MMFSA_D_ADDR], %g2 ;\ 8870Sstevel@tonic-gate /* Fault type not available in MMU fault status area */ ;\ 8880Sstevel@tonic-gate mov MMFSA_F_UNALIGN, %g1 ;\ 8890Sstevel@tonic-gate ldx [%g3 + MMFSA_D_CTX], %g3 ;\ 8900Sstevel@tonic-gate sllx %g3, SFSR_CTX_SHIFT, %g3 ;\ 8910Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_not_aligned ;\ 892526Sarao or %g3, %g1, %g3 /* SFSR */ ;\ 8930Sstevel@tonic-gate .align 32 8940Sstevel@tonic-gate/* 8950Sstevel@tonic-gate * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2) 8964127Sedp */ 8970Sstevel@tonic-gate 898526Sarao/* 899526Sarao * synthesize for trap(): SFAR in %g2, SFSR in %g3 900526Sarao */ 9010Sstevel@tonic-gate#define DMMU_EXC_LDDF_NOT_ALIGNED \ 9020Sstevel@tonic-gate ba,a,pt %xcc, .dmmu_exc_lddf_not_aligned ;\ 9030Sstevel@tonic-gate .align 32 904526Sarao/* 905526Sarao * synthesize for trap(): SFAR in %g2, SFSR in %g3 906526Sarao */ 9070Sstevel@tonic-gate#define DMMU_EXC_STDF_NOT_ALIGNED \ 9080Sstevel@tonic-gate ba,a,pt %xcc, .dmmu_exc_stdf_not_aligned ;\ 9090Sstevel@tonic-gate .align 32 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate#if defined(cscope) 9120Sstevel@tonic-gate/* 9130Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that 9140Sstevel@tonic-gate * are generated by macro expansion of DTLB_MISS(). 9150Sstevel@tonic-gate */ 9160Sstevel@tonic-gate .global tt0_dtlbmiss 9170Sstevel@tonic-gatett0_dtlbmiss: 9180Sstevel@tonic-gate .global tt1_dtlbmiss 9190Sstevel@tonic-gatett1_dtlbmiss: 9200Sstevel@tonic-gate nop 9210Sstevel@tonic-gate#endif 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate/* 9240Sstevel@tonic-gate * Data miss handler (must be exactly 32 instructions) 9250Sstevel@tonic-gate * 9260Sstevel@tonic-gate * This handler is invoked only if the hypervisor has been instructed 9270Sstevel@tonic-gate * not to do any TSB walk. 9280Sstevel@tonic-gate * 9290Sstevel@tonic-gate * Kernel and invalid context cases are handled by the sfmmu_kdtlb_miss 9300Sstevel@tonic-gate * handler. 9310Sstevel@tonic-gate * 9320Sstevel@tonic-gate * User TLB miss handling depends upon whether a user process has one or 9330Sstevel@tonic-gate * two TSBs. User TSB information (physical base and size code) is kept 9340Sstevel@tonic-gate * in two dedicated scratchpad registers. Absence of a user TSB (primarily 9350Sstevel@tonic-gate * second TSB) is indicated by a negative value (-1) in that register. 9360Sstevel@tonic-gate */ 9370Sstevel@tonic-gate 938526Sarao/* 9393687Sjb145095 * synthesize for miss handler: pseudo-tag access in %g2 (with context "type" 9403687Sjb145095 * (0=kernel, 1=invalid, or 2=user) rather than context ID) 941526Sarao */ 9420Sstevel@tonic-gate#define DTLB_MISS(table_name) ;\ 9430Sstevel@tonic-gate .global table_name/**/_dtlbmiss ;\ 9440Sstevel@tonic-gatetable_name/**/_dtlbmiss: ;\ 9453687Sjb145095 GET_MMU_D_PTAGACC_CTXTYPE(%g2, %g3) /* 8 instr */ ;\ 9460Sstevel@tonic-gate cmp %g3, INVALID_CONTEXT ;\ 9470Sstevel@tonic-gate ble,pn %xcc, sfmmu_kdtlb_miss ;\ 9480Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 9490Sstevel@tonic-gate mov SCRATCHPAD_UTSBREG2, %g1 ;\ 9500Sstevel@tonic-gate ldxa [%g1]ASI_SCRATCHPAD, %g1 /* get 2nd tsbreg */ ;\ 9513687Sjb145095 brgez,pn %g1, sfmmu_udtlb_slowpath /* branch if 2 TSBs */ ;\ 9520Sstevel@tonic-gate nop ;\ 9530Sstevel@tonic-gate GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5) /* 11 instr */ ;\ 9540Sstevel@tonic-gate ba,pt %xcc, sfmmu_udtlb_fastpath /* no 4M TSB, miss */ ;\ 9550Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 9560Sstevel@tonic-gate .align 128 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate#if defined(cscope) 9600Sstevel@tonic-gate/* 9610Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that 9620Sstevel@tonic-gate * are generated by macro expansion of ITLB_MISS(). 9630Sstevel@tonic-gate */ 9640Sstevel@tonic-gate .global tt0_itlbmiss 9650Sstevel@tonic-gatett0_itlbmiss: 9660Sstevel@tonic-gate .global tt1_itlbmiss 9670Sstevel@tonic-gatett1_itlbmiss: 9680Sstevel@tonic-gate nop 9690Sstevel@tonic-gate#endif 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate/* 9720Sstevel@tonic-gate * Instruction miss handler. 9730Sstevel@tonic-gate * 9740Sstevel@tonic-gate * This handler is invoked only if the hypervisor has been instructed 9750Sstevel@tonic-gate * not to do any TSB walk. 9760Sstevel@tonic-gate * 9770Sstevel@tonic-gate * ldda instructions will have their ASI patched 9780Sstevel@tonic-gate * by sfmmu_patch_ktsb at runtime. 9790Sstevel@tonic-gate * MUST be EXACTLY 32 instructions or we'll break. 9800Sstevel@tonic-gate */ 9810Sstevel@tonic-gate 982526Sarao/* 9833687Sjb145095 * synthesize for miss handler: TAG_ACCESS in %g2 (with context "type" 9843687Sjb145095 * (0=kernel, 1=invalid, or 2=user) rather than context ID) 985526Sarao */ 9860Sstevel@tonic-gate#define ITLB_MISS(table_name) \ 9870Sstevel@tonic-gate .global table_name/**/_itlbmiss ;\ 9880Sstevel@tonic-gatetable_name/**/_itlbmiss: ;\ 9893687Sjb145095 GET_MMU_I_PTAGACC_CTXTYPE(%g2, %g3) /* 8 instr */ ;\ 9900Sstevel@tonic-gate cmp %g3, INVALID_CONTEXT ;\ 9910Sstevel@tonic-gate ble,pn %xcc, sfmmu_kitlb_miss ;\ 9920Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 9930Sstevel@tonic-gate mov SCRATCHPAD_UTSBREG2, %g1 ;\ 9940Sstevel@tonic-gate ldxa [%g1]ASI_SCRATCHPAD, %g1 /* get 2nd tsbreg */ ;\ 9953687Sjb145095 brgez,pn %g1, sfmmu_uitlb_slowpath /* branch if 2 TSBs */ ;\ 9960Sstevel@tonic-gate nop ;\ 9970Sstevel@tonic-gate GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5) /* 11 instr */ ;\ 9980Sstevel@tonic-gate ba,pt %xcc, sfmmu_uitlb_fastpath /* no 4M TSB, miss */ ;\ 9990Sstevel@tonic-gate srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ 10000Sstevel@tonic-gate .align 128 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate#define DTSB_MISS \ 10030Sstevel@tonic-gate GOTO_TT(sfmmu_slow_dmmu_miss,trace_dmmu) 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate#define ITSB_MISS \ 10060Sstevel@tonic-gate GOTO_TT(sfmmu_slow_immu_miss,trace_immu) 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate/* 10090Sstevel@tonic-gate * This macro is the first level handler for fast protection faults. 10100Sstevel@tonic-gate * It first demaps the tlb entry which generated the fault and then 10110Sstevel@tonic-gate * attempts to set the modify bit on the hash. It needs to be 10120Sstevel@tonic-gate * exactly 32 instructions. 10130Sstevel@tonic-gate */ 1014526Sarao/* 10153687Sjb145095 * synthesize for miss handler: TAG_ACCESS in %g2 (with context "type" 10163687Sjb145095 * (0=kernel, 1=invalid, or 2=user) rather than context ID) 1017526Sarao */ 10180Sstevel@tonic-gate#define DTLB_PROT \ 10193687Sjb145095 GET_MMU_D_PTAGACC_CTXTYPE(%g2, %g3) /* 8 instr */ ;\ 10200Sstevel@tonic-gate /* ;\ 10213687Sjb145095 * g2 = pseudo-tag access register (ctx type rather than ctx ID) ;\ 10223687Sjb145095 * g3 = ctx type (0, 1, or 2) ;\ 10230Sstevel@tonic-gate */ ;\ 10240Sstevel@tonic-gate TT_TRACE(trace_dataprot) /* 2 instr ifdef TRAPTRACE */ ;\ 10250Sstevel@tonic-gate /* clobbers g1 and g6 XXXQ? */ ;\ 10260Sstevel@tonic-gate brnz,pt %g3, sfmmu_uprot_trap /* user trap */ ;\ 10270Sstevel@tonic-gate nop ;\ 10280Sstevel@tonic-gate ba,a,pt %xcc, sfmmu_kprot_trap /* kernel trap */ ;\ 10290Sstevel@tonic-gate .align 128 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate#define DMMU_EXCEPTION_TL1 ;\ 10320Sstevel@tonic-gate ba,a,pt %xcc, mmu_trap_tl1 ;\ 10330Sstevel@tonic-gate .align 32 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate#define MISALIGN_ADDR_TL1 ;\ 10360Sstevel@tonic-gate ba,a,pt %xcc, mmu_trap_tl1 ;\ 10370Sstevel@tonic-gate .align 32 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate/* 10400Sstevel@tonic-gate * Trace a tsb hit 10410Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 10420Sstevel@tonic-gate * g2 = tag access register (in) 10430Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 10440Sstevel@tonic-gate * g5 = tsbe data (in) 10450Sstevel@tonic-gate * g6 = scratch (clobbered) 10460Sstevel@tonic-gate * g7 = pc we jumped here from (in) 10470Sstevel@tonic-gate * ttextra = value to OR in to trap type (%tt) (in) 10480Sstevel@tonic-gate */ 10490Sstevel@tonic-gate#ifdef TRAPTRACE 10500Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra) \ 10510Sstevel@tonic-gate membar #Sync ;\ 10520Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 ;\ 10530Sstevel@tonic-gate flush %g6 ;\ 10540Sstevel@tonic-gate TRACE_PTR(%g3, %g6) ;\ 1055*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) ;\ 10560Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi ;\ 10570Sstevel@tonic-gate stna %g2, [%g3 + TRAP_ENT_SP]%asi /* tag access */ ;\ 10580Sstevel@tonic-gate stna %g5, [%g3 + TRAP_ENT_F1]%asi /* tsb data */ ;\ 10590Sstevel@tonic-gate rdpr %tnpc, %g6 ;\ 10600Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_F2]%asi ;\ 10610Sstevel@tonic-gate stna %g1, [%g3 + TRAP_ENT_F3]%asi /* tsb pointer */ ;\ 10620Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F4]%asi ;\ 10630Sstevel@tonic-gate rdpr %tpc, %g6 ;\ 10640Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_TPC]%asi ;\ 10650Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g3, %g6) ;\ 10660Sstevel@tonic-gate rdpr %tt, %g6 ;\ 10670Sstevel@tonic-gate or %g6, (ttextra), %g1 ;\ 10680Sstevel@tonic-gate stha %g1, [%g3 + TRAP_ENT_TT]%asi ;\ 10690Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g4) ;\ 1070526Sarao mov MMFSA_D_ADDR, %g1 ;\ 10710Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT ;\ 1072526Sarao move %xcc, MMFSA_I_ADDR, %g1 ;\ 10730Sstevel@tonic-gate cmp %g6, T_INSTR_MMU_MISS ;\ 1074526Sarao move %xcc, MMFSA_I_ADDR, %g1 ;\ 1075526Sarao ldx [%g4 + %g1], %g1 ;\ 1076526Sarao stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* fault addr */ ;\ 1077526Sarao mov MMFSA_D_CTX, %g1 ;\ 10780Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT ;\ 1079526Sarao move %xcc, MMFSA_I_CTX, %g1 ;\ 10800Sstevel@tonic-gate cmp %g6, T_INSTR_MMU_MISS ;\ 1081526Sarao move %xcc, MMFSA_I_CTX, %g1 ;\ 1082526Sarao ldx [%g4 + %g1], %g1 ;\ 1083526Sarao stna %g1, [%g3 + TRAP_ENT_TR]%asi ;\ 10840Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g6) 10850Sstevel@tonic-gate#else 10860Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra) 10870Sstevel@tonic-gate#endif 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate#if defined(lint) 10910Sstevel@tonic-gate 10920Sstevel@tonic-gatestruct scb trap_table; 10930Sstevel@tonic-gatestruct scb scb; /* trap_table/scb are the same object */ 10940Sstevel@tonic-gate 10950Sstevel@tonic-gate#else /* lint */ 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate/* 10980Sstevel@tonic-gate * ======================================================================= 10990Sstevel@tonic-gate * SPARC V9 TRAP TABLE 11000Sstevel@tonic-gate * 11010Sstevel@tonic-gate * The trap table is divided into two halves: the first half is used when 11020Sstevel@tonic-gate * taking traps when TL=0; the second half is used when taking traps from 11030Sstevel@tonic-gate * TL>0. Note that handlers in the second half of the table might not be able 11040Sstevel@tonic-gate * to make the same assumptions as handlers in the first half of the table. 11050Sstevel@tonic-gate * 11060Sstevel@tonic-gate * Worst case trap nesting so far: 11070Sstevel@tonic-gate * 11080Sstevel@tonic-gate * at TL=0 client issues software trap requesting service 11090Sstevel@tonic-gate * at TL=1 nucleus wants a register window 11100Sstevel@tonic-gate * at TL=2 register window clean/spill/fill takes a TLB miss 11110Sstevel@tonic-gate * at TL=3 processing TLB miss 11120Sstevel@tonic-gate * at TL=4 handle asynchronous error 11130Sstevel@tonic-gate * 11140Sstevel@tonic-gate * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode". 11150Sstevel@tonic-gate * 11160Sstevel@tonic-gate * ======================================================================= 11170Sstevel@tonic-gate */ 11180Sstevel@tonic-gate .section ".text" 11190Sstevel@tonic-gate .align 4 11200Sstevel@tonic-gate .global trap_table, scb, trap_table0, trap_table1, etrap_table 11211640Spetede .type trap_table, #object 11221640Spetede .type trap_table0, #object 11231640Spetede .type trap_table1, #object 11241640Spetede .type scb, #object 11250Sstevel@tonic-gatetrap_table: 11260Sstevel@tonic-gatescb: 11270Sstevel@tonic-gatetrap_table0: 11280Sstevel@tonic-gate /* hardware traps */ 11290Sstevel@tonic-gate NOT; /* 000 reserved */ 11300Sstevel@tonic-gate RED; /* 001 power on reset */ 11311991Sheppo WATCHDOG_RESET; /* 002 watchdog reset */ 11320Sstevel@tonic-gate RED; /* 003 externally initiated reset */ 11330Sstevel@tonic-gate RED; /* 004 software initiated reset */ 11340Sstevel@tonic-gate RED; /* 005 red mode exception */ 11350Sstevel@tonic-gate NOT; NOT; /* 006 - 007 reserved */ 11360Sstevel@tonic-gate IMMU_EXCEPTION; /* 008 instruction access exception */ 11370Sstevel@tonic-gate ITSB_MISS; /* 009 instruction access MMU miss */ 11380Sstevel@tonic-gate NOT; /* 00A reserved */ 11390Sstevel@tonic-gate NOT; NOT4; /* 00B - 00F reserved */ 11400Sstevel@tonic-gate ILLTRAP_INSTR; /* 010 illegal instruction */ 11410Sstevel@tonic-gate TRAP(T_PRIV_INSTR); /* 011 privileged opcode */ 1142518Swsm TRAP(T_UNIMP_LDD); /* 012 unimplemented LDD */ 1143518Swsm TRAP(T_UNIMP_STD); /* 013 unimplemented STD */ 11440Sstevel@tonic-gate NOT4; NOT4; NOT4; /* 014 - 01F reserved */ 11450Sstevel@tonic-gate FP_DISABLED_TRAP; /* 020 fp disabled */ 11460Sstevel@tonic-gate FP_IEEE_TRAP; /* 021 fp exception ieee 754 */ 11470Sstevel@tonic-gate FP_TRAP; /* 022 fp exception other */ 11480Sstevel@tonic-gate TAG_OVERFLOW; /* 023 tag overflow */ 11490Sstevel@tonic-gate CLEAN_WINDOW; /* 024 - 027 clean window */ 11500Sstevel@tonic-gate DIV_BY_ZERO; /* 028 division by zero */ 11510Sstevel@tonic-gate NOT; /* 029 internal processor error */ 11520Sstevel@tonic-gate NOT; NOT; NOT4; /* 02A - 02F reserved */ 11530Sstevel@tonic-gate DMMU_EXCEPTION; /* 030 data access exception */ 11540Sstevel@tonic-gate DTSB_MISS; /* 031 data access MMU miss */ 11550Sstevel@tonic-gate NOT; /* 032 reserved */ 11560Sstevel@tonic-gate NOT; /* 033 data access protection */ 11570Sstevel@tonic-gate DMMU_EXC_AG_NOT_ALIGNED; /* 034 mem address not aligned */ 11580Sstevel@tonic-gate DMMU_EXC_LDDF_NOT_ALIGNED; /* 035 LDDF mem address not aligned */ 11590Sstevel@tonic-gate DMMU_EXC_STDF_NOT_ALIGNED; /* 036 STDF mem address not aligned */ 11600Sstevel@tonic-gate DMMU_EXC_AG_PRIV; /* 037 privileged action */ 11610Sstevel@tonic-gate NOT; /* 038 LDQF mem address not aligned */ 11620Sstevel@tonic-gate NOT; /* 039 STQF mem address not aligned */ 11630Sstevel@tonic-gate NOT; NOT; NOT4; /* 03A - 03F reserved */ 11640Sstevel@tonic-gate NOT; /* 040 async data error */ 11650Sstevel@tonic-gate LEVEL_INTERRUPT(1); /* 041 interrupt level 1 */ 11660Sstevel@tonic-gate LEVEL_INTERRUPT(2); /* 042 interrupt level 2 */ 11670Sstevel@tonic-gate LEVEL_INTERRUPT(3); /* 043 interrupt level 3 */ 11680Sstevel@tonic-gate LEVEL_INTERRUPT(4); /* 044 interrupt level 4 */ 11690Sstevel@tonic-gate LEVEL_INTERRUPT(5); /* 045 interrupt level 5 */ 11700Sstevel@tonic-gate LEVEL_INTERRUPT(6); /* 046 interrupt level 6 */ 11710Sstevel@tonic-gate LEVEL_INTERRUPT(7); /* 047 interrupt level 7 */ 11720Sstevel@tonic-gate LEVEL_INTERRUPT(8); /* 048 interrupt level 8 */ 11730Sstevel@tonic-gate LEVEL_INTERRUPT(9); /* 049 interrupt level 9 */ 11740Sstevel@tonic-gate LEVEL_INTERRUPT(10); /* 04A interrupt level 10 */ 11750Sstevel@tonic-gate LEVEL_INTERRUPT(11); /* 04B interrupt level 11 */ 11760Sstevel@tonic-gate LEVEL_INTERRUPT(12); /* 04C interrupt level 12 */ 11770Sstevel@tonic-gate LEVEL_INTERRUPT(13); /* 04D interrupt level 13 */ 11780Sstevel@tonic-gate LEVEL14_INTERRUPT; /* 04E interrupt level 14 */ 11798803SJonathan.Haslam@Sun.COM LEVEL15_INTERRUPT; /* 04F interrupt level 15 */ 11800Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 050 - 05F reserved */ 11810Sstevel@tonic-gate NOT; /* 060 interrupt vector */ 11820Sstevel@tonic-gate GOTO(kmdb_trap); /* 061 PA watchpoint */ 11830Sstevel@tonic-gate GOTO(kmdb_trap); /* 062 VA watchpoint */ 11840Sstevel@tonic-gate NOT; /* 063 reserved */ 11850Sstevel@tonic-gate ITLB_MISS(tt0); /* 064 instruction access MMU miss */ 11860Sstevel@tonic-gate DTLB_MISS(tt0); /* 068 data access MMU miss */ 11870Sstevel@tonic-gate DTLB_PROT; /* 06C data access protection */ 11880Sstevel@tonic-gate NOT; /* 070 reserved */ 11890Sstevel@tonic-gate NOT; /* 071 reserved */ 11900Sstevel@tonic-gate NOT; /* 072 reserved */ 11910Sstevel@tonic-gate NOT; /* 073 reserved */ 11920Sstevel@tonic-gate NOT4; NOT4 /* 074 - 07B reserved */ 11930Sstevel@tonic-gate CPU_MONDO; /* 07C cpu_mondo */ 11940Sstevel@tonic-gate DEV_MONDO; /* 07D dev_mondo */ 11950Sstevel@tonic-gate GOTO_TT(resumable_error, trace_gen); /* 07E resumable error */ 11960Sstevel@tonic-gate GOTO_TT(nonresumable_error, trace_gen); /* 07F non-reasumable error */ 11970Sstevel@tonic-gate NOT4; /* 080 spill 0 normal */ 11980Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUP,sn0); /* 084 spill 1 normal */ 11990Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUP,sn0); /* 088 spill 2 normal */ 12000Sstevel@tonic-gate SPILL_32clean(ASI_AIUP,sn0); /* 08C spill 3 normal */ 12010Sstevel@tonic-gate SPILL_64clean(ASI_AIUP,sn0); /* 090 spill 4 normal */ 12020Sstevel@tonic-gate SPILL_32bit(not); /* 094 spill 5 normal */ 12030Sstevel@tonic-gate SPILL_64bit(not); /* 098 spill 6 normal */ 12040Sstevel@tonic-gate SPILL_mixed; /* 09C spill 7 normal */ 12050Sstevel@tonic-gate NOT4; /* 0A0 spill 0 other */ 12060Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUS,so0); /* 0A4 spill 1 other */ 12070Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUS,so0); /* 0A8 spill 2 other */ 12080Sstevel@tonic-gate SPILL_32bit_asi(ASI_AIUS,so0); /* 0AC spill 3 other */ 12090Sstevel@tonic-gate SPILL_64bit_asi(ASI_AIUS,so0); /* 0B0 spill 4 other */ 12100Sstevel@tonic-gate NOT4; /* 0B4 spill 5 other */ 12110Sstevel@tonic-gate NOT4; /* 0B8 spill 6 other */ 12120Sstevel@tonic-gate NOT4; /* 0BC spill 7 other */ 12130Sstevel@tonic-gate NOT4; /* 0C0 fill 0 normal */ 12140Sstevel@tonic-gate FILL_32bit_asi(ASI_AIUP,fn0); /* 0C4 fill 1 normal */ 12150Sstevel@tonic-gate FILL_64bit_asi(ASI_AIUP,fn0); /* 0C8 fill 2 normal */ 12160Sstevel@tonic-gate FILL_32bit_asi(ASI_AIUP,fn0); /* 0CC fill 3 normal */ 12170Sstevel@tonic-gate FILL_64bit_asi(ASI_AIUP,fn0); /* 0D0 fill 4 normal */ 12180Sstevel@tonic-gate FILL_32bit(not); /* 0D4 fill 5 normal */ 12190Sstevel@tonic-gate FILL_64bit(not); /* 0D8 fill 6 normal */ 12200Sstevel@tonic-gate FILL_mixed; /* 0DC fill 7 normal */ 12210Sstevel@tonic-gate NOT4; /* 0E0 fill 0 other */ 12220Sstevel@tonic-gate NOT4; /* 0E4 fill 1 other */ 12230Sstevel@tonic-gate NOT4; /* 0E8 fill 2 other */ 12240Sstevel@tonic-gate NOT4; /* 0EC fill 3 other */ 12250Sstevel@tonic-gate NOT4; /* 0F0 fill 4 other */ 12260Sstevel@tonic-gate NOT4; /* 0F4 fill 5 other */ 12270Sstevel@tonic-gate NOT4; /* 0F8 fill 6 other */ 12280Sstevel@tonic-gate NOT4; /* 0FC fill 7 other */ 12290Sstevel@tonic-gate /* user traps */ 12300Sstevel@tonic-gate GOTO(syscall_trap_4x); /* 100 old system call */ 12310Sstevel@tonic-gate TRAP(T_BREAKPOINT); /* 101 user breakpoint */ 12320Sstevel@tonic-gate TRAP(T_DIV0); /* 102 user divide by zero */ 12330Sstevel@tonic-gate GOTO(.flushw); /* 103 flush windows */ 12340Sstevel@tonic-gate GOTO(.clean_windows); /* 104 clean windows */ 12350Sstevel@tonic-gate BAD; /* 105 range check ?? */ 12360Sstevel@tonic-gate GOTO(.fix_alignment); /* 106 do unaligned references */ 12370Sstevel@tonic-gate BAD; /* 107 unused */ 12384141Sedp SYSCALL_TRAP32; /* 108 ILP32 system call on LP64 */ 12390Sstevel@tonic-gate GOTO(set_trap0_addr); /* 109 set trap0 address */ 12400Sstevel@tonic-gate BAD; BAD; BAD4; /* 10A - 10F unused */ 12410Sstevel@tonic-gate TRP4; TRP4; TRP4; TRP4; /* 110 - 11F V9 user trap handlers */ 12420Sstevel@tonic-gate GOTO(.getcc); /* 120 get condition codes */ 12430Sstevel@tonic-gate GOTO(.setcc); /* 121 set condition codes */ 12440Sstevel@tonic-gate GOTO(.getpsr); /* 122 get psr */ 12450Sstevel@tonic-gate GOTO(.setpsr); /* 123 set psr (some fields) */ 12460Sstevel@tonic-gate GOTO(get_timestamp); /* 124 get timestamp */ 12470Sstevel@tonic-gate GOTO(get_virtime); /* 125 get lwp virtual time */ 12480Sstevel@tonic-gate PRIV(self_xcall); /* 126 self xcall */ 12490Sstevel@tonic-gate GOTO(get_hrestime); /* 127 get hrestime */ 12500Sstevel@tonic-gate BAD; /* 128 ST_SETV9STACK */ 12510Sstevel@tonic-gate GOTO(.getlgrp); /* 129 get lgrpid */ 12520Sstevel@tonic-gate BAD; BAD; BAD4; /* 12A - 12F unused */ 12530Sstevel@tonic-gate BAD4; BAD4; /* 130 - 137 unused */ 12540Sstevel@tonic-gate DTRACE_PID; /* 138 dtrace pid tracing provider */ 12552179Sahl BAD; /* 139 unused */ 12560Sstevel@tonic-gate DTRACE_RETURN; /* 13A dtrace pid return probe */ 12570Sstevel@tonic-gate BAD; BAD4; /* 13B - 13F unused */ 12584141Sedp SYSCALL_TRAP; /* 140 LP64 system call */ 12591321Srscott SYSCALL(nosys); /* 141 unused system call trap */ 12600Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL 12610Sstevel@tonic-gate GOTO(.traptrace_freeze); /* 142 freeze traptrace */ 12620Sstevel@tonic-gate GOTO(.traptrace_unfreeze); /* 143 unfreeze traptrace */ 12630Sstevel@tonic-gate#else 12641321Srscott SYSCALL(nosys); /* 142 unused system call trap */ 12651321Srscott SYSCALL(nosys); /* 143 unused system call trap */ 12660Sstevel@tonic-gate#endif 12670Sstevel@tonic-gate BAD4; BAD4; BAD4; /* 144 - 14F unused */ 12680Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 150 - 15F unused */ 12690Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 160 - 16F unused */ 12700Sstevel@tonic-gate BAD; /* 170 - unused */ 12710Sstevel@tonic-gate BAD; /* 171 - unused */ 12720Sstevel@tonic-gate BAD; BAD; /* 172 - 173 unused */ 12730Sstevel@tonic-gate BAD4; BAD4; /* 174 - 17B unused */ 12740Sstevel@tonic-gate#ifdef PTL1_PANIC_DEBUG 12750Sstevel@tonic-gate mov PTL1_BAD_DEBUG, %g1; GOTO(ptl1_panic); 12760Sstevel@tonic-gate /* 17C test ptl1_panic */ 12770Sstevel@tonic-gate#else 12780Sstevel@tonic-gate BAD; /* 17C unused */ 12790Sstevel@tonic-gate#endif /* PTL1_PANIC_DEBUG */ 12800Sstevel@tonic-gate PRIV(kmdb_trap); /* 17D kmdb enter (L1-A) */ 12810Sstevel@tonic-gate PRIV(kmdb_trap); /* 17E kmdb breakpoint */ 12820Sstevel@tonic-gate PRIV(obp_bpt); /* 17F obp breakpoint */ 12830Sstevel@tonic-gate /* reserved */ 12840Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 180 - 18F reserved */ 12850Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 190 - 19F reserved */ 12860Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1A0 - 1AF reserved */ 12870Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1B0 - 1BF reserved */ 12880Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1C0 - 1CF reserved */ 12890Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1D0 - 1DF reserved */ 12900Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1E0 - 1EF reserved */ 12910Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1F0 - 1FF reserved */ 12920Sstevel@tonic-gate .size trap_table0, (.-trap_table0) 12930Sstevel@tonic-gatetrap_table1: 12940Sstevel@tonic-gate NOT4; NOT4; /* 000 - 007 unused */ 12950Sstevel@tonic-gate NOT; /* 008 instruction access exception */ 12960Sstevel@tonic-gate ITSB_MISS; /* 009 instruction access MMU miss */ 12970Sstevel@tonic-gate NOT; /* 00A reserved */ 12980Sstevel@tonic-gate NOT; NOT4; /* 00B - 00F unused */ 12990Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 010 - 01F unused */ 13000Sstevel@tonic-gate NOT4; /* 020 - 023 unused */ 13010Sstevel@tonic-gate CLEAN_WINDOW; /* 024 - 027 clean window */ 13020Sstevel@tonic-gate NOT4; NOT4; /* 028 - 02F unused */ 13030Sstevel@tonic-gate DMMU_EXCEPTION_TL1; /* 030 data access exception */ 13040Sstevel@tonic-gate DTSB_MISS; /* 031 data access MMU miss */ 13050Sstevel@tonic-gate NOT; /* 032 reserved */ 13060Sstevel@tonic-gate NOT; /* 033 unused */ 13070Sstevel@tonic-gate MISALIGN_ADDR_TL1; /* 034 mem address not aligned */ 13080Sstevel@tonic-gate NOT; NOT; NOT; NOT4; NOT4 /* 035 - 03F unused */ 13090Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 040 - 04F unused */ 13100Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 050 - 05F unused */ 13110Sstevel@tonic-gate NOT; /* 060 unused */ 13120Sstevel@tonic-gate GOTO(kmdb_trap_tl1); /* 061 PA watchpoint */ 13130Sstevel@tonic-gate GOTO(kmdb_trap_tl1); /* 062 VA watchpoint */ 13140Sstevel@tonic-gate NOT; /* 063 reserved */ 13150Sstevel@tonic-gate ITLB_MISS(tt1); /* 064 instruction access MMU miss */ 13160Sstevel@tonic-gate DTLB_MISS(tt1); /* 068 data access MMU miss */ 13170Sstevel@tonic-gate DTLB_PROT; /* 06C data access protection */ 13180Sstevel@tonic-gate NOT; /* 070 reserved */ 13190Sstevel@tonic-gate NOT; /* 071 reserved */ 13200Sstevel@tonic-gate NOT; /* 072 reserved */ 13210Sstevel@tonic-gate NOT; /* 073 reserved */ 1322817Swh94709 NOT4; NOT4; /* 074 - 07B reserved */ 1323817Swh94709 NOT; /* 07C reserved */ 1324817Swh94709 NOT; /* 07D reserved */ 1325817Swh94709 NOT; /* 07E resumable error */ 1326817Swh94709 GOTO_TT(nonresumable_error, trace_gen); /* 07F nonresumable error */ 13270Sstevel@tonic-gate NOTP4; /* 080 spill 0 normal */ 13280Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUP,sn1); /* 084 spill 1 normal */ 13290Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUP,sn1); /* 088 spill 2 normal */ 13300Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUP,sn1); /* 08C spill 3 normal */ 13310Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUP,sn1); /* 090 spill 4 normal */ 13320Sstevel@tonic-gate NOTP4; /* 094 spill 5 normal */ 13330Sstevel@tonic-gate SPILL_64bit_ktt1(sk); /* 098 spill 6 normal */ 13340Sstevel@tonic-gate SPILL_mixed_ktt1(sk); /* 09C spill 7 normal */ 13350Sstevel@tonic-gate NOTP4; /* 0A0 spill 0 other */ 13360Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUS,so1); /* 0A4 spill 1 other */ 13370Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUS,so1); /* 0A8 spill 2 other */ 13380Sstevel@tonic-gate SPILL_32bit_tt1(ASI_AIUS,so1); /* 0AC spill 3 other */ 13390Sstevel@tonic-gate SPILL_64bit_tt1(ASI_AIUS,so1); /* 0B0 spill 4 other */ 13400Sstevel@tonic-gate NOTP4; /* 0B4 spill 5 other */ 13410Sstevel@tonic-gate NOTP4; /* 0B8 spill 6 other */ 13420Sstevel@tonic-gate NOTP4; /* 0BC spill 7 other */ 13430Sstevel@tonic-gate NOT4; /* 0C0 fill 0 normal */ 13440Sstevel@tonic-gate NOT4; /* 0C4 fill 1 normal */ 13450Sstevel@tonic-gate NOT4; /* 0C8 fill 2 normal */ 13460Sstevel@tonic-gate NOT4; /* 0CC fill 3 normal */ 13470Sstevel@tonic-gate NOT4; /* 0D0 fill 4 normal */ 13480Sstevel@tonic-gate NOT4; /* 0D4 fill 5 normal */ 13490Sstevel@tonic-gate NOT4; /* 0D8 fill 6 normal */ 13500Sstevel@tonic-gate NOT4; /* 0DC fill 7 normal */ 13510Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 0E0 - 0EF unused */ 13520Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 0F0 - 0FF unused */ 13530Sstevel@tonic-gate/* 13540Sstevel@tonic-gate * Code running at TL>0 does not use soft traps, so 13550Sstevel@tonic-gate * we can truncate the table here. 13560Sstevel@tonic-gate * However: 13570Sstevel@tonic-gate * sun4v uses (hypervisor) ta instructions at TL > 0, so 13580Sstevel@tonic-gate * provide a safety net for now. 13590Sstevel@tonic-gate */ 13600Sstevel@tonic-gate /* soft traps */ 13610Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 100 - 10F unused */ 13620Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 110 - 11F unused */ 13630Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 120 - 12F unused */ 13640Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 130 - 13F unused */ 13650Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 140 - 14F unused */ 13660Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 150 - 15F unused */ 13670Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 160 - 16F unused */ 13680Sstevel@tonic-gate BAD4; BAD4; BAD4; BAD4; /* 170 - 17F unused */ 13690Sstevel@tonic-gate /* reserved */ 13700Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 180 - 18F reserved */ 13710Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 190 - 19F reserved */ 13720Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1A0 - 1AF reserved */ 13730Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1B0 - 1BF reserved */ 13740Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1C0 - 1CF reserved */ 13750Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1D0 - 1DF reserved */ 13760Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1E0 - 1EF reserved */ 13770Sstevel@tonic-gate NOT4; NOT4; NOT4; NOT4; /* 1F0 - 1FF reserved */ 13780Sstevel@tonic-gateetrap_table: 13790Sstevel@tonic-gate .size trap_table1, (.-trap_table1) 13800Sstevel@tonic-gate .size trap_table, (.-trap_table) 13810Sstevel@tonic-gate .size scb, (.-scb) 13820Sstevel@tonic-gate 13830Sstevel@tonic-gate/* 13840Sstevel@tonic-gate * We get to exec_fault in the case of an instruction miss and tte 13850Sstevel@tonic-gate * has no execute bit set. We go to tl0 to handle it. 13860Sstevel@tonic-gate * 13870Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 13880Sstevel@tonic-gate * g2 = tag access register (in) 13890Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 13900Sstevel@tonic-gate * g5 = tsbe data (in) 13910Sstevel@tonic-gate * g6 = scratch (clobbered) 13920Sstevel@tonic-gate * g7 = pc we jumped here from (in) 13930Sstevel@tonic-gate */ 1394526Sarao/* 13953687Sjb145095 * synthesize for miss handler: TAG_ACCESS in %g2 (with context "type" 13963687Sjb145095 * (0=kernel, 1=invalid, or 2=user) rather than context ID) 1397526Sarao */ 13980Sstevel@tonic-gate ALTENTRY(exec_fault) 13990Sstevel@tonic-gate TRACE_TSBHIT(TT_MMU_EXEC) 14000Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g4) 14010Sstevel@tonic-gate ldx [%g4 + MMFSA_I_ADDR], %g2 /* g2 = address */ 14020Sstevel@tonic-gate ldx [%g4 + MMFSA_I_CTX], %g3 /* g3 = ctx */ 14030Sstevel@tonic-gate srlx %g2, MMU_PAGESHIFT, %g2 ! align address to page boundry 14043687Sjb145095 cmp %g3, USER_CONTEXT_TYPE 14050Sstevel@tonic-gate sllx %g2, MMU_PAGESHIFT, %g2 14063687Sjb145095 movgu %icc, USER_CONTEXT_TYPE, %g3 1407526Sarao or %g2, %g3, %g2 /* TAG_ACCESS */ 14080Sstevel@tonic-gate mov T_INSTR_MMU_MISS, %g3 ! arg2 = traptype 14090Sstevel@tonic-gate set trap, %g1 14100Sstevel@tonic-gate ba,pt %xcc, sys_trap 14110Sstevel@tonic-gate mov -1, %g4 14120Sstevel@tonic-gate 14130Sstevel@tonic-gate.mmu_exception_not_aligned: 14140Sstevel@tonic-gate /* %g2 = sfar, %g3 = sfsr */ 14150Sstevel@tonic-gate rdpr %tstate, %g1 14160Sstevel@tonic-gate btst TSTATE_PRIV, %g1 14170Sstevel@tonic-gate bnz,pn %icc, 2f 14180Sstevel@tonic-gate nop 14190Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 14200Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 14210Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 14220Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 14230Sstevel@tonic-gate brz,pt %g5, 2f 14240Sstevel@tonic-gate nop 14250Sstevel@tonic-gate ldn [%g5 + P_UTRAP15], %g5 ! unaligned utrap? 14260Sstevel@tonic-gate brz,pn %g5, 2f 14270Sstevel@tonic-gate nop 14280Sstevel@tonic-gate btst 1, %sp 14290Sstevel@tonic-gate bz,pt %xcc, 1f ! 32 bit user program 14300Sstevel@tonic-gate nop 14310Sstevel@tonic-gate ba,pt %xcc, .setup_v9utrap ! 64 bit user program 14320Sstevel@tonic-gate nop 14330Sstevel@tonic-gate1: 14340Sstevel@tonic-gate ba,pt %xcc, .setup_utrap 14350Sstevel@tonic-gate or %g2, %g0, %g7 14360Sstevel@tonic-gate2: 14370Sstevel@tonic-gate ba,pt %xcc, .mmu_exception_end 14380Sstevel@tonic-gate mov T_ALIGNMENT, %g1 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate.mmu_priv_exception: 14410Sstevel@tonic-gate rdpr %tstate, %g1 14420Sstevel@tonic-gate btst TSTATE_PRIV, %g1 14430Sstevel@tonic-gate bnz,pn %icc, 1f 14440Sstevel@tonic-gate nop 14450Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 14460Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 14470Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 14480Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 14490Sstevel@tonic-gate brz,pt %g5, 1f 14500Sstevel@tonic-gate nop 14510Sstevel@tonic-gate ldn [%g5 + P_UTRAP16], %g5 14520Sstevel@tonic-gate brnz,pt %g5, .setup_v9utrap 14530Sstevel@tonic-gate nop 14540Sstevel@tonic-gate1: 14550Sstevel@tonic-gate mov T_PRIV_INSTR, %g1 14560Sstevel@tonic-gate 14570Sstevel@tonic-gate.mmu_exception_end: 14580Sstevel@tonic-gate CPU_INDEX(%g4, %g5) 14590Sstevel@tonic-gate set cpu_core, %g5 14600Sstevel@tonic-gate sllx %g4, CPU_CORE_SHIFT, %g4 14610Sstevel@tonic-gate add %g4, %g5, %g4 14620Sstevel@tonic-gate lduh [%g4 + CPUC_DTRACE_FLAGS], %g5 14630Sstevel@tonic-gate andcc %g5, CPU_DTRACE_NOFAULT, %g0 14640Sstevel@tonic-gate bz 1f 14650Sstevel@tonic-gate or %g5, CPU_DTRACE_BADADDR, %g5 14660Sstevel@tonic-gate stuh %g5, [%g4 + CPUC_DTRACE_FLAGS] 14670Sstevel@tonic-gate done 14680Sstevel@tonic-gate 14690Sstevel@tonic-gate1: 14700Sstevel@tonic-gate sllx %g3, 32, %g3 14710Sstevel@tonic-gate or %g3, %g1, %g3 14720Sstevel@tonic-gate set trap, %g1 14730Sstevel@tonic-gate ba,pt %xcc, sys_trap 14740Sstevel@tonic-gate sub %g0, 1, %g4 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate.fp_disabled: 14770Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 14780Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 14790Sstevel@tonic-gate rdpr %tstate, %g4 14800Sstevel@tonic-gate btst TSTATE_PRIV, %g4 14810Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 14820Sstevel@tonic-gate mov PTL1_BAD_FPTRAP, %g1 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 14850Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 14860Sstevel@tonic-gate brz,a,pt %g5, 2f 14870Sstevel@tonic-gate nop 14880Sstevel@tonic-gate ldn [%g5 + P_UTRAP7], %g5 ! fp_disabled utrap? 14890Sstevel@tonic-gate brz,a,pn %g5, 2f 14900Sstevel@tonic-gate nop 14910Sstevel@tonic-gate btst 1, %sp 14920Sstevel@tonic-gate bz,a,pt %xcc, 1f ! 32 bit user program 14930Sstevel@tonic-gate nop 14940Sstevel@tonic-gate ba,a,pt %xcc, .setup_v9utrap ! 64 bit user program 14950Sstevel@tonic-gate nop 14960Sstevel@tonic-gate1: 14970Sstevel@tonic-gate ba,pt %xcc, .setup_utrap 14980Sstevel@tonic-gate or %g0, %g0, %g7 14990Sstevel@tonic-gate2: 15000Sstevel@tonic-gate set fp_disabled, %g1 15010Sstevel@tonic-gate ba,pt %xcc, sys_trap 15020Sstevel@tonic-gate sub %g0, 1, %g4 15030Sstevel@tonic-gate 15040Sstevel@tonic-gate.fp_ieee_exception: 15050Sstevel@tonic-gate rdpr %tstate, %g1 15060Sstevel@tonic-gate btst TSTATE_PRIV, %g1 15070Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 15080Sstevel@tonic-gate mov PTL1_BAD_FPTRAP, %g1 15090Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 15100Sstevel@tonic-gate stx %fsr, [%g1 + CPU_TMP1] 15110Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %g2 15120Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 15130Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 ! load proc pointer 15140Sstevel@tonic-gate ldn [%g1 + P_UTRAPS], %g5 ! are there utraps? 15150Sstevel@tonic-gate brz,a,pt %g5, 1f 15160Sstevel@tonic-gate nop 15170Sstevel@tonic-gate ldn [%g5 + P_UTRAP8], %g5 15180Sstevel@tonic-gate brnz,a,pt %g5, .setup_v9utrap 15190Sstevel@tonic-gate nop 15200Sstevel@tonic-gate1: 15210Sstevel@tonic-gate set _fp_ieee_exception, %g1 15220Sstevel@tonic-gate ba,pt %xcc, sys_trap 15230Sstevel@tonic-gate sub %g0, 1, %g4 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate/* 15260Sstevel@tonic-gate * Register Inputs: 15270Sstevel@tonic-gate * %g5 user trap handler 15280Sstevel@tonic-gate * %g7 misaligned addr - for alignment traps only 15290Sstevel@tonic-gate */ 15300Sstevel@tonic-gate.setup_utrap: 15310Sstevel@tonic-gate set trap, %g1 ! setup in case we go 15320Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 ! through sys_trap on 15330Sstevel@tonic-gate sub %g0, 1, %g4 ! the save instruction below 15340Sstevel@tonic-gate 15350Sstevel@tonic-gate /* 15360Sstevel@tonic-gate * If the DTrace pid provider is single stepping a copied-out 15370Sstevel@tonic-gate * instruction, t->t_dtrace_step will be set. In that case we need 15380Sstevel@tonic-gate * to abort the single-stepping (since execution of the instruction 15390Sstevel@tonic-gate * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 15400Sstevel@tonic-gate */ 15410Sstevel@tonic-gate save %sp, -SA(MINFRAME32), %sp ! window for trap handler 15420Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 15430Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 15440Sstevel@tonic-gate ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step 15450Sstevel@tonic-gate rdpr %tnpc, %l2 ! arg1 == tnpc 15460Sstevel@tonic-gate brz,pt %g2, 1f 15470Sstevel@tonic-gate rdpr %tpc, %l1 ! arg0 == tpc 15480Sstevel@tonic-gate 15490Sstevel@tonic-gate ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast 15500Sstevel@tonic-gate ldn [%g1 + T_DTRACE_NPC], %l2 ! arg1 = t->t_dtrace_npc (step) 15510Sstevel@tonic-gate brz,pt %g2, 1f 15520Sstevel@tonic-gate st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags 15530Sstevel@tonic-gate stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast 15540Sstevel@tonic-gate1: 15550Sstevel@tonic-gate mov %g7, %l3 ! arg2 == misaligned address 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate rdpr %tstate, %g1 ! cwp for trap handler 15580Sstevel@tonic-gate rdpr %cwp, %g4 15590Sstevel@tonic-gate bclr TSTATE_CWP_MASK, %g1 15600Sstevel@tonic-gate wrpr %g1, %g4, %tstate 15610Sstevel@tonic-gate wrpr %g0, %g5, %tnpc ! trap handler address 15620Sstevel@tonic-gate FAST_TRAP_DONE 15630Sstevel@tonic-gate /* NOTREACHED */ 15640Sstevel@tonic-gate 15650Sstevel@tonic-gate.check_v9utrap: 15660Sstevel@tonic-gate rdpr %tstate, %g1 15670Sstevel@tonic-gate btst TSTATE_PRIV, %g1 15680Sstevel@tonic-gate bnz,a,pn %icc, 3f 15690Sstevel@tonic-gate nop 15700Sstevel@tonic-gate CPU_ADDR(%g4, %g1) ! load CPU struct addr 15710Sstevel@tonic-gate ldn [%g4 + CPU_THREAD], %g5 ! load thread pointer 15720Sstevel@tonic-gate ldn [%g5 + T_PROCP], %g5 ! load proc pointer 15730Sstevel@tonic-gate ldn [%g5 + P_UTRAPS], %g5 ! are there utraps? 15740Sstevel@tonic-gate 15750Sstevel@tonic-gate cmp %g3, T_SOFTWARE_TRAP 15760Sstevel@tonic-gate bne,a,pt %icc, 1f 15770Sstevel@tonic-gate nop 15780Sstevel@tonic-gate 15790Sstevel@tonic-gate brz,pt %g5, 3f ! if p_utraps == NULL goto trap() 15800Sstevel@tonic-gate rdpr %tt, %g3 ! delay - get actual hw trap type 15814127Sedp 15820Sstevel@tonic-gate sub %g3, 254, %g1 ! UT_TRAP_INSTRUCTION_16 = p_utraps[18] 15830Sstevel@tonic-gate ba,pt %icc, 2f 15840Sstevel@tonic-gate smul %g1, CPTRSIZE, %g2 15850Sstevel@tonic-gate1: 15860Sstevel@tonic-gate brz,a,pt %g5, 3f ! if p_utraps == NULL goto trap() 15870Sstevel@tonic-gate nop 15880Sstevel@tonic-gate 15890Sstevel@tonic-gate cmp %g3, T_UNIMP_INSTR 15900Sstevel@tonic-gate bne,a,pt %icc, 2f 15910Sstevel@tonic-gate nop 15920Sstevel@tonic-gate 15930Sstevel@tonic-gate mov 1, %g1 15940Sstevel@tonic-gate st %g1, [%g4 + CPU_TL1_HDLR] ! set CPU_TL1_HDLR 15954127Sedp rdpr %tpc, %g1 ! ld trapping instruction using 15960Sstevel@tonic-gate lduwa [%g1]ASI_AIUP, %g1 ! "AS IF USER" ASI which could fault 15970Sstevel@tonic-gate st %g0, [%g4 + CPU_TL1_HDLR] ! clr CPU_TL1_HDLR 15980Sstevel@tonic-gate 15990Sstevel@tonic-gate sethi %hi(0xc1c00000), %g4 ! setup mask for illtrap instruction 16000Sstevel@tonic-gate andcc %g1, %g4, %g4 ! and instruction with mask 16010Sstevel@tonic-gate bnz,a,pt %icc, 3f ! if %g4 == zero, %g1 is an ILLTRAP 16020Sstevel@tonic-gate nop ! fall thru to setup 16034127Sedp2: 16040Sstevel@tonic-gate ldn [%g5 + %g2], %g5 16050Sstevel@tonic-gate brnz,a,pt %g5, .setup_v9utrap 16060Sstevel@tonic-gate nop 16070Sstevel@tonic-gate3: 16080Sstevel@tonic-gate set trap, %g1 16090Sstevel@tonic-gate ba,pt %xcc, sys_trap 16100Sstevel@tonic-gate sub %g0, 1, %g4 16110Sstevel@tonic-gate /* NOTREACHED */ 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate/* 16140Sstevel@tonic-gate * Register Inputs: 16150Sstevel@tonic-gate * %g5 user trap handler 16160Sstevel@tonic-gate */ 16170Sstevel@tonic-gate.setup_v9utrap: 16180Sstevel@tonic-gate set trap, %g1 ! setup in case we go 16190Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 ! through sys_trap on 16200Sstevel@tonic-gate sub %g0, 1, %g4 ! the save instruction below 16210Sstevel@tonic-gate 16220Sstevel@tonic-gate /* 16230Sstevel@tonic-gate * If the DTrace pid provider is single stepping a copied-out 16240Sstevel@tonic-gate * instruction, t->t_dtrace_step will be set. In that case we need 16250Sstevel@tonic-gate * to abort the single-stepping (since execution of the instruction 16260Sstevel@tonic-gate * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 16270Sstevel@tonic-gate */ 16280Sstevel@tonic-gate save %sp, -SA(MINFRAME64), %sp ! window for trap handler 16290Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 16300Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 16310Sstevel@tonic-gate ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step 16320Sstevel@tonic-gate rdpr %tnpc, %l7 ! arg1 == tnpc 16330Sstevel@tonic-gate brz,pt %g2, 1f 16340Sstevel@tonic-gate rdpr %tpc, %l6 ! arg0 == tpc 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast 16370Sstevel@tonic-gate ldn [%g1 + T_DTRACE_NPC], %l7 ! arg1 == t->t_dtrace_npc (step) 16380Sstevel@tonic-gate brz,pt %g2, 1f 16390Sstevel@tonic-gate st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags 16400Sstevel@tonic-gate stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast 16410Sstevel@tonic-gate1: 16420Sstevel@tonic-gate rdpr %tstate, %g2 ! cwp for trap handler 16430Sstevel@tonic-gate rdpr %cwp, %g4 16440Sstevel@tonic-gate bclr TSTATE_CWP_MASK, %g2 16450Sstevel@tonic-gate wrpr %g2, %g4, %tstate 16460Sstevel@tonic-gate 16470Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g4 ! load proc pointer 16480Sstevel@tonic-gate ldn [%g4 + P_AS], %g4 ! load as pointer 16490Sstevel@tonic-gate ldn [%g4 + A_USERLIMIT], %g4 ! load as userlimit 16500Sstevel@tonic-gate cmp %l7, %g4 ! check for single-step set 16510Sstevel@tonic-gate bne,pt %xcc, 4f 16520Sstevel@tonic-gate nop 16530Sstevel@tonic-gate ldn [%g1 + T_LWP], %g1 ! load klwp pointer 16540Sstevel@tonic-gate ld [%g1 + PCB_STEP], %g4 ! load single-step flag 16550Sstevel@tonic-gate cmp %g4, STEP_ACTIVE ! step flags set in pcb? 16560Sstevel@tonic-gate bne,pt %icc, 4f 16570Sstevel@tonic-gate nop 16580Sstevel@tonic-gate stn %g5, [%g1 + PCB_TRACEPC] ! save trap handler addr in pcb 16590Sstevel@tonic-gate mov %l7, %g4 ! on entry to precise user trap 16600Sstevel@tonic-gate add %l6, 4, %l7 ! handler, %l6 == pc, %l7 == npc 16610Sstevel@tonic-gate ! at time of trap 16620Sstevel@tonic-gate wrpr %g0, %g4, %tnpc ! generate FLTBOUNDS, 16630Sstevel@tonic-gate ! %g4 == userlimit 16640Sstevel@tonic-gate FAST_TRAP_DONE 16650Sstevel@tonic-gate /* NOTREACHED */ 16660Sstevel@tonic-gate4: 16670Sstevel@tonic-gate wrpr %g0, %g5, %tnpc ! trap handler address 16680Sstevel@tonic-gate FAST_TRAP_DONE_CHK_INTR 16690Sstevel@tonic-gate /* NOTREACHED */ 16700Sstevel@tonic-gate 16710Sstevel@tonic-gate.fp_exception: 16720Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 16730Sstevel@tonic-gate stx %fsr, [%g1 + CPU_TMP1] 16740Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %g2 16750Sstevel@tonic-gate 16760Sstevel@tonic-gate /* 16770Sstevel@tonic-gate * Cheetah takes unfinished_FPop trap for certain range of operands 16780Sstevel@tonic-gate * to the "fitos" instruction. Instead of going through the slow 16790Sstevel@tonic-gate * software emulation path, we try to simulate the "fitos" instruction 16800Sstevel@tonic-gate * via "fitod" and "fdtos" provided the following conditions are met: 16810Sstevel@tonic-gate * 16820Sstevel@tonic-gate * fpu_exists is set (if DEBUG) 16830Sstevel@tonic-gate * not in privileged mode 16840Sstevel@tonic-gate * ftt is unfinished_FPop 16850Sstevel@tonic-gate * NXM IEEE trap is not enabled 16860Sstevel@tonic-gate * instruction at %tpc is "fitos" 16870Sstevel@tonic-gate * 16880Sstevel@tonic-gate * Usage: 16890Sstevel@tonic-gate * %g1 per cpu address 16900Sstevel@tonic-gate * %g2 %fsr 16910Sstevel@tonic-gate * %g6 user instruction 16920Sstevel@tonic-gate * 16930Sstevel@tonic-gate * Note that we can take a memory access related trap while trying 16940Sstevel@tonic-gate * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR 16950Sstevel@tonic-gate * flag to catch those traps and let the SFMMU code deal with page 16960Sstevel@tonic-gate * fault and data access exception. 16970Sstevel@tonic-gate */ 16980Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 16990Sstevel@tonic-gate sethi %hi(fpu_exists), %g7 17000Sstevel@tonic-gate ld [%g7 + %lo(fpu_exists)], %g7 17010Sstevel@tonic-gate brz,pn %g7, .fp_exception_cont 17020Sstevel@tonic-gate nop 17030Sstevel@tonic-gate#endif 17040Sstevel@tonic-gate rdpr %tstate, %g7 ! branch if in privileged mode 17050Sstevel@tonic-gate btst TSTATE_PRIV, %g7 17060Sstevel@tonic-gate bnz,pn %xcc, .fp_exception_cont 17070Sstevel@tonic-gate srl %g2, FSR_FTT_SHIFT, %g7 ! extract ftt from %fsr 17080Sstevel@tonic-gate and %g7, (FSR_FTT>>FSR_FTT_SHIFT), %g7 17090Sstevel@tonic-gate cmp %g7, FTT_UNFIN 17104127Sedp set FSR_TEM_NX, %g5 17110Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if NOT unfinished_FPop 17120Sstevel@tonic-gate andcc %g2, %g5, %g0 17130Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if FSR_TEM_NX enabled 17140Sstevel@tonic-gate rdpr %tpc, %g5 ! get faulting PC 17150Sstevel@tonic-gate 17160Sstevel@tonic-gate or %g0, 1, %g7 17170Sstevel@tonic-gate st %g7, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 17180Sstevel@tonic-gate lda [%g5]ASI_USER, %g6 ! get user's instruction 17190Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate set FITOS_INSTR_MASK, %g7 17220Sstevel@tonic-gate and %g6, %g7, %g7 17230Sstevel@tonic-gate set FITOS_INSTR, %g5 17240Sstevel@tonic-gate cmp %g7, %g5 17250Sstevel@tonic-gate bne,pn %xcc, .fp_exception_cont ! branch if not FITOS_INSTR 17260Sstevel@tonic-gate nop 17270Sstevel@tonic-gate 17280Sstevel@tonic-gate /* 17290Sstevel@tonic-gate * This is unfinished FPops trap for "fitos" instruction. We 17300Sstevel@tonic-gate * need to simulate "fitos" via "fitod" and "fdtos" instruction 17310Sstevel@tonic-gate * sequence. 17320Sstevel@tonic-gate * 17330Sstevel@tonic-gate * We need a temporary FP register to do the conversion. Since 17340Sstevel@tonic-gate * both source and destination operands for the "fitos" instruction 17350Sstevel@tonic-gate * have to be within %f0-%f31, we use an FP register from the upper 17360Sstevel@tonic-gate * half to guarantee that it won't collide with the source or the 17370Sstevel@tonic-gate * dest operand. However, we do have to save and restore its value. 17380Sstevel@tonic-gate * 17390Sstevel@tonic-gate * We use %d62 as a temporary FP register for the conversion and 17400Sstevel@tonic-gate * branch to appropriate instruction within the conversion tables 17410Sstevel@tonic-gate * based upon the rs2 and rd values. 17420Sstevel@tonic-gate */ 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate std %d62, [%g1 + CPU_TMP1] ! save original value 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate srl %g6, FITOS_RS2_SHIFT, %g7 17470Sstevel@tonic-gate and %g7, FITOS_REG_MASK, %g7 17480Sstevel@tonic-gate set _fitos_fitod_table, %g4 17490Sstevel@tonic-gate sllx %g7, 2, %g7 17500Sstevel@tonic-gate jmp %g4 + %g7 17510Sstevel@tonic-gate ba,pt %xcc, _fitos_fitod_done 17520Sstevel@tonic-gate .empty 17530Sstevel@tonic-gate 17540Sstevel@tonic-gate_fitos_fitod_table: 17550Sstevel@tonic-gate fitod %f0, %d62 17560Sstevel@tonic-gate fitod %f1, %d62 17570Sstevel@tonic-gate fitod %f2, %d62 17580Sstevel@tonic-gate fitod %f3, %d62 17590Sstevel@tonic-gate fitod %f4, %d62 17600Sstevel@tonic-gate fitod %f5, %d62 17610Sstevel@tonic-gate fitod %f6, %d62 17620Sstevel@tonic-gate fitod %f7, %d62 17630Sstevel@tonic-gate fitod %f8, %d62 17640Sstevel@tonic-gate fitod %f9, %d62 17650Sstevel@tonic-gate fitod %f10, %d62 17660Sstevel@tonic-gate fitod %f11, %d62 17670Sstevel@tonic-gate fitod %f12, %d62 17680Sstevel@tonic-gate fitod %f13, %d62 17690Sstevel@tonic-gate fitod %f14, %d62 17700Sstevel@tonic-gate fitod %f15, %d62 17710Sstevel@tonic-gate fitod %f16, %d62 17720Sstevel@tonic-gate fitod %f17, %d62 17730Sstevel@tonic-gate fitod %f18, %d62 17740Sstevel@tonic-gate fitod %f19, %d62 17750Sstevel@tonic-gate fitod %f20, %d62 17760Sstevel@tonic-gate fitod %f21, %d62 17770Sstevel@tonic-gate fitod %f22, %d62 17780Sstevel@tonic-gate fitod %f23, %d62 17790Sstevel@tonic-gate fitod %f24, %d62 17800Sstevel@tonic-gate fitod %f25, %d62 17810Sstevel@tonic-gate fitod %f26, %d62 17820Sstevel@tonic-gate fitod %f27, %d62 17830Sstevel@tonic-gate fitod %f28, %d62 17840Sstevel@tonic-gate fitod %f29, %d62 17850Sstevel@tonic-gate fitod %f30, %d62 17860Sstevel@tonic-gate fitod %f31, %d62 17870Sstevel@tonic-gate_fitos_fitod_done: 17880Sstevel@tonic-gate 17890Sstevel@tonic-gate /* 17900Sstevel@tonic-gate * Now convert data back into single precision 17910Sstevel@tonic-gate */ 17920Sstevel@tonic-gate srl %g6, FITOS_RD_SHIFT, %g7 17930Sstevel@tonic-gate and %g7, FITOS_REG_MASK, %g7 17940Sstevel@tonic-gate set _fitos_fdtos_table, %g4 17950Sstevel@tonic-gate sllx %g7, 2, %g7 17960Sstevel@tonic-gate jmp %g4 + %g7 17970Sstevel@tonic-gate ba,pt %xcc, _fitos_fdtos_done 17980Sstevel@tonic-gate .empty 17990Sstevel@tonic-gate 18000Sstevel@tonic-gate_fitos_fdtos_table: 18010Sstevel@tonic-gate fdtos %d62, %f0 18020Sstevel@tonic-gate fdtos %d62, %f1 18030Sstevel@tonic-gate fdtos %d62, %f2 18040Sstevel@tonic-gate fdtos %d62, %f3 18050Sstevel@tonic-gate fdtos %d62, %f4 18060Sstevel@tonic-gate fdtos %d62, %f5 18070Sstevel@tonic-gate fdtos %d62, %f6 18080Sstevel@tonic-gate fdtos %d62, %f7 18090Sstevel@tonic-gate fdtos %d62, %f8 18100Sstevel@tonic-gate fdtos %d62, %f9 18110Sstevel@tonic-gate fdtos %d62, %f10 18120Sstevel@tonic-gate fdtos %d62, %f11 18130Sstevel@tonic-gate fdtos %d62, %f12 18140Sstevel@tonic-gate fdtos %d62, %f13 18150Sstevel@tonic-gate fdtos %d62, %f14 18160Sstevel@tonic-gate fdtos %d62, %f15 18170Sstevel@tonic-gate fdtos %d62, %f16 18180Sstevel@tonic-gate fdtos %d62, %f17 18190Sstevel@tonic-gate fdtos %d62, %f18 18200Sstevel@tonic-gate fdtos %d62, %f19 18210Sstevel@tonic-gate fdtos %d62, %f20 18220Sstevel@tonic-gate fdtos %d62, %f21 18230Sstevel@tonic-gate fdtos %d62, %f22 18240Sstevel@tonic-gate fdtos %d62, %f23 18250Sstevel@tonic-gate fdtos %d62, %f24 18260Sstevel@tonic-gate fdtos %d62, %f25 18270Sstevel@tonic-gate fdtos %d62, %f26 18280Sstevel@tonic-gate fdtos %d62, %f27 18290Sstevel@tonic-gate fdtos %d62, %f28 18300Sstevel@tonic-gate fdtos %d62, %f29 18310Sstevel@tonic-gate fdtos %d62, %f30 18320Sstevel@tonic-gate fdtos %d62, %f31 18330Sstevel@tonic-gate_fitos_fdtos_done: 18340Sstevel@tonic-gate 18350Sstevel@tonic-gate ldd [%g1 + CPU_TMP1], %d62 ! restore %d62 18360Sstevel@tonic-gate 18370Sstevel@tonic-gate#if DEBUG 18380Sstevel@tonic-gate /* 18390Sstevel@tonic-gate * Update FPop_unfinished trap kstat 18400Sstevel@tonic-gate */ 18410Sstevel@tonic-gate set fpustat+FPUSTAT_UNFIN_KSTAT, %g7 18420Sstevel@tonic-gate ldx [%g7], %g5 18430Sstevel@tonic-gate1: 18440Sstevel@tonic-gate add %g5, 1, %g6 18454127Sedp 18460Sstevel@tonic-gate casxa [%g7] ASI_N, %g5, %g6 18470Sstevel@tonic-gate cmp %g5, %g6 18480Sstevel@tonic-gate bne,a,pn %xcc, 1b 18490Sstevel@tonic-gate or %g0, %g6, %g5 18500Sstevel@tonic-gate 18510Sstevel@tonic-gate /* 18520Sstevel@tonic-gate * Update fpu_sim_fitos kstat 18530Sstevel@tonic-gate */ 18540Sstevel@tonic-gate set fpuinfo+FPUINFO_FITOS_KSTAT, %g7 18550Sstevel@tonic-gate ldx [%g7], %g5 18560Sstevel@tonic-gate1: 18570Sstevel@tonic-gate add %g5, 1, %g6 18580Sstevel@tonic-gate 18590Sstevel@tonic-gate casxa [%g7] ASI_N, %g5, %g6 18600Sstevel@tonic-gate cmp %g5, %g6 18610Sstevel@tonic-gate bne,a,pn %xcc, 1b 18620Sstevel@tonic-gate or %g0, %g6, %g5 18630Sstevel@tonic-gate#endif /* DEBUG */ 18640Sstevel@tonic-gate 18650Sstevel@tonic-gate FAST_TRAP_DONE 18660Sstevel@tonic-gate 18670Sstevel@tonic-gate.fp_exception_cont: 18680Sstevel@tonic-gate /* 18690Sstevel@tonic-gate * Let _fp_exception deal with simulating FPop instruction. 18700Sstevel@tonic-gate * Note that we need to pass %fsr in %g2 (already read above). 18710Sstevel@tonic-gate */ 18720Sstevel@tonic-gate 18730Sstevel@tonic-gate set _fp_exception, %g1 18740Sstevel@tonic-gate ba,pt %xcc, sys_trap 18750Sstevel@tonic-gate sub %g0, 1, %g4 18760Sstevel@tonic-gate 18770Sstevel@tonic-gate 18780Sstevel@tonic-gate/* 18790Sstevel@tonic-gate * Register windows 18800Sstevel@tonic-gate */ 18810Sstevel@tonic-gate.flushw: 18821647Smb158278.clean_windows: 18830Sstevel@tonic-gate rdpr %tnpc, %g1 18840Sstevel@tonic-gate wrpr %g1, %tpc 18850Sstevel@tonic-gate add %g1, 4, %g1 18860Sstevel@tonic-gate wrpr %g1, %tnpc 18870Sstevel@tonic-gate set trap, %g1 18880Sstevel@tonic-gate mov T_FLUSH_PCB, %g3 18890Sstevel@tonic-gate ba,pt %xcc, sys_trap 18900Sstevel@tonic-gate sub %g0, 1, %g4 18910Sstevel@tonic-gate 18920Sstevel@tonic-gate/* 18930Sstevel@tonic-gate * .spill_clean: clean the previous window, restore the wstate, and 18940Sstevel@tonic-gate * "done". 18950Sstevel@tonic-gate * 18960Sstevel@tonic-gate * Entry: %g7 contains new wstate 18970Sstevel@tonic-gate */ 18980Sstevel@tonic-gate.spill_clean: 18990Sstevel@tonic-gate sethi %hi(nwin_minus_one), %g5 19000Sstevel@tonic-gate ld [%g5 + %lo(nwin_minus_one)], %g5 ! %g5 = nwin - 1 19010Sstevel@tonic-gate rdpr %cwp, %g6 ! %g6 = %cwp 19020Sstevel@tonic-gate deccc %g6 ! %g6-- 19030Sstevel@tonic-gate movneg %xcc, %g5, %g6 ! if (%g6<0) %g6 = nwin-1 19040Sstevel@tonic-gate wrpr %g6, %cwp 19050Sstevel@tonic-gate TT_TRACE_L(trace_win) 19060Sstevel@tonic-gate clr %l0 19070Sstevel@tonic-gate clr %l1 19080Sstevel@tonic-gate clr %l2 19090Sstevel@tonic-gate clr %l3 19100Sstevel@tonic-gate clr %l4 19110Sstevel@tonic-gate clr %l5 19120Sstevel@tonic-gate clr %l6 19130Sstevel@tonic-gate clr %l7 19140Sstevel@tonic-gate wrpr %g0, %g7, %wstate 19150Sstevel@tonic-gate saved 19160Sstevel@tonic-gate retry ! restores correct %cwp 19170Sstevel@tonic-gate 19180Sstevel@tonic-gate.fix_alignment: 19190Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 19200Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer 19210Sstevel@tonic-gate ldn [%g1 + T_PROCP], %g1 19220Sstevel@tonic-gate mov 1, %g2 19230Sstevel@tonic-gate stb %g2, [%g1 + P_FIXALIGNMENT] 19240Sstevel@tonic-gate FAST_TRAP_DONE 19250Sstevel@tonic-gate 19260Sstevel@tonic-gate#define STDF_REG(REG, ADDR, TMP) \ 19270Sstevel@tonic-gate sll REG, 3, REG ;\ 19280Sstevel@tonic-gatemark1: set start1, TMP ;\ 19290Sstevel@tonic-gate jmp REG + TMP ;\ 19300Sstevel@tonic-gate nop ;\ 19310Sstevel@tonic-gatestart1: ba,pt %xcc, done1 ;\ 19320Sstevel@tonic-gate std %f0, [ADDR + CPU_TMP1] ;\ 19330Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19340Sstevel@tonic-gate std %f32, [ADDR + CPU_TMP1] ;\ 19350Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19360Sstevel@tonic-gate std %f2, [ADDR + CPU_TMP1] ;\ 19370Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19380Sstevel@tonic-gate std %f34, [ADDR + CPU_TMP1] ;\ 19390Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19400Sstevel@tonic-gate std %f4, [ADDR + CPU_TMP1] ;\ 19410Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19420Sstevel@tonic-gate std %f36, [ADDR + CPU_TMP1] ;\ 19430Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19440Sstevel@tonic-gate std %f6, [ADDR + CPU_TMP1] ;\ 19450Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19460Sstevel@tonic-gate std %f38, [ADDR + CPU_TMP1] ;\ 19470Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19480Sstevel@tonic-gate std %f8, [ADDR + CPU_TMP1] ;\ 19490Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19500Sstevel@tonic-gate std %f40, [ADDR + CPU_TMP1] ;\ 19510Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19520Sstevel@tonic-gate std %f10, [ADDR + CPU_TMP1] ;\ 19530Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19540Sstevel@tonic-gate std %f42, [ADDR + CPU_TMP1] ;\ 19550Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19560Sstevel@tonic-gate std %f12, [ADDR + CPU_TMP1] ;\ 19570Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19580Sstevel@tonic-gate std %f44, [ADDR + CPU_TMP1] ;\ 19590Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19600Sstevel@tonic-gate std %f14, [ADDR + CPU_TMP1] ;\ 19610Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19620Sstevel@tonic-gate std %f46, [ADDR + CPU_TMP1] ;\ 19630Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19640Sstevel@tonic-gate std %f16, [ADDR + CPU_TMP1] ;\ 19650Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19660Sstevel@tonic-gate std %f48, [ADDR + CPU_TMP1] ;\ 19670Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19680Sstevel@tonic-gate std %f18, [ADDR + CPU_TMP1] ;\ 19690Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19700Sstevel@tonic-gate std %f50, [ADDR + CPU_TMP1] ;\ 19710Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19720Sstevel@tonic-gate std %f20, [ADDR + CPU_TMP1] ;\ 19730Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19740Sstevel@tonic-gate std %f52, [ADDR + CPU_TMP1] ;\ 19750Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19760Sstevel@tonic-gate std %f22, [ADDR + CPU_TMP1] ;\ 19770Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19780Sstevel@tonic-gate std %f54, [ADDR + CPU_TMP1] ;\ 19790Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19800Sstevel@tonic-gate std %f24, [ADDR + CPU_TMP1] ;\ 19810Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19820Sstevel@tonic-gate std %f56, [ADDR + CPU_TMP1] ;\ 19830Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19840Sstevel@tonic-gate std %f26, [ADDR + CPU_TMP1] ;\ 19850Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19860Sstevel@tonic-gate std %f58, [ADDR + CPU_TMP1] ;\ 19870Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19880Sstevel@tonic-gate std %f28, [ADDR + CPU_TMP1] ;\ 19890Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19900Sstevel@tonic-gate std %f60, [ADDR + CPU_TMP1] ;\ 19910Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19920Sstevel@tonic-gate std %f30, [ADDR + CPU_TMP1] ;\ 19930Sstevel@tonic-gate ba,pt %xcc, done1 ;\ 19940Sstevel@tonic-gate std %f62, [ADDR + CPU_TMP1] ;\ 19950Sstevel@tonic-gatedone1: 19960Sstevel@tonic-gate 19970Sstevel@tonic-gate#define LDDF_REG(REG, ADDR, TMP) \ 19980Sstevel@tonic-gate sll REG, 3, REG ;\ 19990Sstevel@tonic-gatemark2: set start2, TMP ;\ 20000Sstevel@tonic-gate jmp REG + TMP ;\ 20010Sstevel@tonic-gate nop ;\ 20020Sstevel@tonic-gatestart2: ba,pt %xcc, done2 ;\ 20030Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f0 ;\ 20040Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20050Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f32 ;\ 20060Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20070Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f2 ;\ 20080Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20090Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f34 ;\ 20100Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20110Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f4 ;\ 20120Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20130Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f36 ;\ 20140Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20150Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f6 ;\ 20160Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20170Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f38 ;\ 20180Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20190Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f8 ;\ 20200Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20210Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f40 ;\ 20220Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20230Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f10 ;\ 20240Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20250Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f42 ;\ 20260Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20270Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f12 ;\ 20280Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20290Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f44 ;\ 20300Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20310Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f14 ;\ 20320Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20330Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f46 ;\ 20340Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20350Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f16 ;\ 20360Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20370Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f48 ;\ 20380Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20390Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f18 ;\ 20400Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20410Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f50 ;\ 20420Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20430Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f20 ;\ 20440Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20450Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f52 ;\ 20460Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20470Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f22 ;\ 20480Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20490Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f54 ;\ 20500Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20510Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f24 ;\ 20520Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20530Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f56 ;\ 20540Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20550Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f26 ;\ 20560Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20570Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f58 ;\ 20580Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20590Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f28 ;\ 20600Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20610Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f60 ;\ 20620Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20630Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f30 ;\ 20640Sstevel@tonic-gate ba,pt %xcc, done2 ;\ 20650Sstevel@tonic-gate ldd [ADDR + CPU_TMP1], %f62 ;\ 20660Sstevel@tonic-gatedone2: 20670Sstevel@tonic-gate 20680Sstevel@tonic-gate.lddf_exception_not_aligned: 20690Sstevel@tonic-gate /* %g2 = sfar, %g3 = sfsr */ 20700Sstevel@tonic-gate mov %g2, %g5 ! stash sfar 20710Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 20720Sstevel@tonic-gate sethi %hi(fpu_exists), %g2 ! check fpu_exists 20730Sstevel@tonic-gate ld [%g2 + %lo(fpu_exists)], %g2 20740Sstevel@tonic-gate brz,a,pn %g2, 4f 20750Sstevel@tonic-gate nop 20760Sstevel@tonic-gate#endif 20770Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 20780Sstevel@tonic-gate or %g0, 1, %g4 20790Sstevel@tonic-gate st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 20800Sstevel@tonic-gate 20810Sstevel@tonic-gate rdpr %tpc, %g2 20820Sstevel@tonic-gate lda [%g2]ASI_AIUP, %g6 ! get the user's lddf instruction 20830Sstevel@tonic-gate srl %g6, 23, %g1 ! using ldda or not? 20840Sstevel@tonic-gate and %g1, 1, %g1 20850Sstevel@tonic-gate brz,a,pt %g1, 2f ! check for ldda instruction 20860Sstevel@tonic-gate nop 20870Sstevel@tonic-gate srl %g6, 13, %g1 ! check immflag 20880Sstevel@tonic-gate and %g1, 1, %g1 20890Sstevel@tonic-gate rdpr %tstate, %g2 ! %tstate in %g2 20900Sstevel@tonic-gate brnz,a,pn %g1, 1f 20910Sstevel@tonic-gate srl %g2, 31, %g1 ! get asi from %tstate 20920Sstevel@tonic-gate srl %g6, 5, %g1 ! get asi from instruction 20930Sstevel@tonic-gate and %g1, 0xFF, %g1 ! imm_asi field 20940Sstevel@tonic-gate1: 20950Sstevel@tonic-gate cmp %g1, ASI_P ! primary address space 20960Sstevel@tonic-gate be,a,pt %icc, 2f 20970Sstevel@tonic-gate nop 20980Sstevel@tonic-gate cmp %g1, ASI_PNF ! primary no fault address space 20990Sstevel@tonic-gate be,a,pt %icc, 2f 21000Sstevel@tonic-gate nop 21010Sstevel@tonic-gate cmp %g1, ASI_S ! secondary address space 21020Sstevel@tonic-gate be,a,pt %icc, 2f 21030Sstevel@tonic-gate nop 21040Sstevel@tonic-gate cmp %g1, ASI_SNF ! secondary no fault address space 21050Sstevel@tonic-gate bne,a,pn %icc, 3f 21060Sstevel@tonic-gate nop 21070Sstevel@tonic-gate2: 21080Sstevel@tonic-gate lduwa [%g5]ASI_USER, %g7 ! get first half of misaligned data 21090Sstevel@tonic-gate add %g5, 4, %g5 ! increment misaligned data address 21100Sstevel@tonic-gate lduwa [%g5]ASI_USER, %g5 ! get second half of misaligned data 21110Sstevel@tonic-gate 21120Sstevel@tonic-gate sllx %g7, 32, %g7 21130Sstevel@tonic-gate or %g5, %g7, %g5 ! combine data 21140Sstevel@tonic-gate CPU_ADDR(%g7, %g1) ! save data on a per-cpu basis 21150Sstevel@tonic-gate stx %g5, [%g7 + CPU_TMP1] ! save in cpu_tmp1 21160Sstevel@tonic-gate 21170Sstevel@tonic-gate srl %g6, 25, %g3 ! %g6 has the instruction 21180Sstevel@tonic-gate and %g3, 0x1F, %g3 ! %g3 has rd 21190Sstevel@tonic-gate LDDF_REG(%g3, %g7, %g4) 21200Sstevel@tonic-gate 21210Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 21220Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 21230Sstevel@tonic-gate FAST_TRAP_DONE 21240Sstevel@tonic-gate3: 21250Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 21260Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 21270Sstevel@tonic-gate4: 21280Sstevel@tonic-gate set T_USER, %g3 ! trap type in %g3 21290Sstevel@tonic-gate or %g3, T_LDDF_ALIGN, %g3 21300Sstevel@tonic-gate mov %g5, %g2 ! misaligned vaddr in %g2 21310Sstevel@tonic-gate set fpu_trap, %g1 ! goto C for the little and 21320Sstevel@tonic-gate ba,pt %xcc, sys_trap ! no fault little asi's 21330Sstevel@tonic-gate sub %g0, 1, %g4 21340Sstevel@tonic-gate 21350Sstevel@tonic-gate.stdf_exception_not_aligned: 21360Sstevel@tonic-gate /* %g2 = sfar, %g3 = sfsr */ 21370Sstevel@tonic-gate mov %g2, %g5 21380Sstevel@tonic-gate 21390Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 21400Sstevel@tonic-gate sethi %hi(fpu_exists), %g7 ! check fpu_exists 21410Sstevel@tonic-gate ld [%g7 + %lo(fpu_exists)], %g3 21420Sstevel@tonic-gate brz,a,pn %g3, 4f 21430Sstevel@tonic-gate nop 21440Sstevel@tonic-gate#endif 21450Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 21460Sstevel@tonic-gate or %g0, 1, %g4 21470Sstevel@tonic-gate st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag 21480Sstevel@tonic-gate 21490Sstevel@tonic-gate rdpr %tpc, %g2 21500Sstevel@tonic-gate lda [%g2]ASI_AIUP, %g6 ! get the user's stdf instruction 21510Sstevel@tonic-gate 21520Sstevel@tonic-gate srl %g6, 23, %g1 ! using stda or not? 21530Sstevel@tonic-gate and %g1, 1, %g1 21540Sstevel@tonic-gate brz,a,pt %g1, 2f ! check for stda instruction 21550Sstevel@tonic-gate nop 21560Sstevel@tonic-gate srl %g6, 13, %g1 ! check immflag 21570Sstevel@tonic-gate and %g1, 1, %g1 21580Sstevel@tonic-gate rdpr %tstate, %g2 ! %tstate in %g2 21590Sstevel@tonic-gate brnz,a,pn %g1, 1f 21600Sstevel@tonic-gate srl %g2, 31, %g1 ! get asi from %tstate 21610Sstevel@tonic-gate srl %g6, 5, %g1 ! get asi from instruction 21620Sstevel@tonic-gate and %g1, 0xff, %g1 ! imm_asi field 21630Sstevel@tonic-gate1: 21640Sstevel@tonic-gate cmp %g1, ASI_P ! primary address space 21650Sstevel@tonic-gate be,a,pt %icc, 2f 21660Sstevel@tonic-gate nop 21670Sstevel@tonic-gate cmp %g1, ASI_S ! secondary address space 21680Sstevel@tonic-gate bne,a,pn %icc, 3f 21690Sstevel@tonic-gate nop 21700Sstevel@tonic-gate2: 21710Sstevel@tonic-gate srl %g6, 25, %g6 21720Sstevel@tonic-gate and %g6, 0x1F, %g6 ! %g6 has rd 21730Sstevel@tonic-gate CPU_ADDR(%g7, %g1) 21740Sstevel@tonic-gate STDF_REG(%g6, %g7, %g4) ! STDF_REG(REG, ADDR, TMP) 21750Sstevel@tonic-gate 21760Sstevel@tonic-gate ldx [%g7 + CPU_TMP1], %g6 21770Sstevel@tonic-gate srlx %g6, 32, %g7 21780Sstevel@tonic-gate stuwa %g7, [%g5]ASI_USER ! first half 21790Sstevel@tonic-gate add %g5, 4, %g5 ! increment misaligned data address 21800Sstevel@tonic-gate stuwa %g6, [%g5]ASI_USER ! second half 21810Sstevel@tonic-gate 21820Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 21830Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 21840Sstevel@tonic-gate FAST_TRAP_DONE 21850Sstevel@tonic-gate3: 21860Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 21870Sstevel@tonic-gate st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 21880Sstevel@tonic-gate4: 21890Sstevel@tonic-gate set T_USER, %g3 ! trap type in %g3 21900Sstevel@tonic-gate or %g3, T_STDF_ALIGN, %g3 21910Sstevel@tonic-gate mov %g5, %g2 ! misaligned vaddr in %g2 21920Sstevel@tonic-gate set fpu_trap, %g1 ! goto C for the little and 21930Sstevel@tonic-gate ba,pt %xcc, sys_trap ! nofault little asi's 21940Sstevel@tonic-gate sub %g0, 1, %g4 21950Sstevel@tonic-gate 21960Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL 21970Sstevel@tonic-gate 21980Sstevel@tonic-gate.traptrace_freeze: 21990Sstevel@tonic-gate mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4 22000Sstevel@tonic-gate TT_TRACE_L(trace_win) 22010Sstevel@tonic-gate mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0 22020Sstevel@tonic-gate set trap_freeze, %g1 22030Sstevel@tonic-gate mov 1, %g2 22040Sstevel@tonic-gate st %g2, [%g1] 22050Sstevel@tonic-gate FAST_TRAP_DONE 22060Sstevel@tonic-gate 22070Sstevel@tonic-gate.traptrace_unfreeze: 22080Sstevel@tonic-gate set trap_freeze, %g1 22090Sstevel@tonic-gate st %g0, [%g1] 22100Sstevel@tonic-gate mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4 22110Sstevel@tonic-gate TT_TRACE_L(trace_win) 22120Sstevel@tonic-gate mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0 22130Sstevel@tonic-gate FAST_TRAP_DONE 22140Sstevel@tonic-gate 22150Sstevel@tonic-gate#endif /* DEBUG_USER_TRAPTRACECTL */ 22160Sstevel@tonic-gate 22170Sstevel@tonic-gate.getcc: 22180Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 22190Sstevel@tonic-gate stx %o0, [%g1 + CPU_TMP1] ! save %o0 22200Sstevel@tonic-gate rdpr %tstate, %g3 ! get tstate 22210Sstevel@tonic-gate srlx %g3, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr 22220Sstevel@tonic-gate set PSR_ICC, %g2 22230Sstevel@tonic-gate and %o0, %g2, %o0 ! mask out the rest 22240Sstevel@tonic-gate srl %o0, PSR_ICC_SHIFT, %o0 ! right justify 22250Sstevel@tonic-gate wrpr %g0, 0, %gl 22260Sstevel@tonic-gate mov %o0, %g1 ! move ccr to normal %g1 22270Sstevel@tonic-gate wrpr %g0, 1, %gl 22280Sstevel@tonic-gate ! cannot assume globals retained their values after increasing %gl 22290Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 22300Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %o0 ! restore %o0 22310Sstevel@tonic-gate FAST_TRAP_DONE 22320Sstevel@tonic-gate 22330Sstevel@tonic-gate.setcc: 22340Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 22350Sstevel@tonic-gate stx %o0, [%g1 + CPU_TMP1] ! save %o0 22360Sstevel@tonic-gate wrpr %g0, 0, %gl 22370Sstevel@tonic-gate mov %g1, %o0 22380Sstevel@tonic-gate wrpr %g0, 1, %gl 22390Sstevel@tonic-gate ! cannot assume globals retained their values after increasing %gl 22400Sstevel@tonic-gate CPU_ADDR(%g1, %g2) 22410Sstevel@tonic-gate sll %o0, PSR_ICC_SHIFT, %g2 22420Sstevel@tonic-gate set PSR_ICC, %g3 22430Sstevel@tonic-gate and %g2, %g3, %g2 ! mask out rest 22440Sstevel@tonic-gate sllx %g2, PSR_TSTATE_CC_SHIFT, %g2 22450Sstevel@tonic-gate rdpr %tstate, %g3 ! get tstate 22460Sstevel@tonic-gate srl %g3, 0, %g3 ! clear upper word 22470Sstevel@tonic-gate or %g3, %g2, %g3 ! or in new bits 22480Sstevel@tonic-gate wrpr %g3, %tstate 22490Sstevel@tonic-gate ldx [%g1 + CPU_TMP1], %o0 ! restore %o0 22500Sstevel@tonic-gate FAST_TRAP_DONE 22510Sstevel@tonic-gate 22520Sstevel@tonic-gate/* 22530Sstevel@tonic-gate * getpsr(void) 22540Sstevel@tonic-gate * Note that the xcc part of the ccr is not provided. 22550Sstevel@tonic-gate * The V8 code shows why the V9 trap is not faster: 22560Sstevel@tonic-gate * #define GETPSR_TRAP() \ 22570Sstevel@tonic-gate * mov %psr, %i0; jmp %l2; rett %l2+4; nop; 22580Sstevel@tonic-gate */ 22590Sstevel@tonic-gate 22600Sstevel@tonic-gate .type .getpsr, #function 22610Sstevel@tonic-gate.getpsr: 22620Sstevel@tonic-gate rdpr %tstate, %g1 ! get tstate 22630Sstevel@tonic-gate srlx %g1, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr 22640Sstevel@tonic-gate set PSR_ICC, %g2 22650Sstevel@tonic-gate and %o0, %g2, %o0 ! mask out the rest 22660Sstevel@tonic-gate 22670Sstevel@tonic-gate rd %fprs, %g1 ! get fprs 22680Sstevel@tonic-gate and %g1, FPRS_FEF, %g2 ! mask out dirty upper/lower 22690Sstevel@tonic-gate sllx %g2, PSR_FPRS_FEF_SHIFT, %g2 ! shift fef to V8 psr.ef 22700Sstevel@tonic-gate or %o0, %g2, %o0 ! or result into psr.ef 22710Sstevel@tonic-gate 22720Sstevel@tonic-gate set V9_PSR_IMPLVER, %g2 ! SI assigned impl/ver: 0xef 22730Sstevel@tonic-gate or %o0, %g2, %o0 ! or psr.impl/ver 22740Sstevel@tonic-gate FAST_TRAP_DONE 22750Sstevel@tonic-gate SET_SIZE(.getpsr) 22760Sstevel@tonic-gate 22770Sstevel@tonic-gate/* 22780Sstevel@tonic-gate * setpsr(newpsr) 22790Sstevel@tonic-gate * Note that there is no support for ccr.xcc in the V9 code. 22800Sstevel@tonic-gate */ 22810Sstevel@tonic-gate 22820Sstevel@tonic-gate .type .setpsr, #function 22830Sstevel@tonic-gate.setpsr: 22840Sstevel@tonic-gate rdpr %tstate, %g1 ! get tstate 22850Sstevel@tonic-gate! setx TSTATE_V8_UBITS, %g2 22860Sstevel@tonic-gate or %g0, CCR_ICC, %g3 22870Sstevel@tonic-gate sllx %g3, TSTATE_CCR_SHIFT, %g2 22880Sstevel@tonic-gate 22890Sstevel@tonic-gate andn %g1, %g2, %g1 ! zero current user bits 22900Sstevel@tonic-gate set PSR_ICC, %g2 22910Sstevel@tonic-gate and %g2, %o0, %g2 ! clear all but psr.icc bits 22920Sstevel@tonic-gate sllx %g2, PSR_TSTATE_CC_SHIFT, %g3 ! shift to tstate.ccr.icc 22930Sstevel@tonic-gate wrpr %g1, %g3, %tstate ! write tstate 22940Sstevel@tonic-gate 22950Sstevel@tonic-gate set PSR_EF, %g2 22960Sstevel@tonic-gate and %g2, %o0, %g2 ! clear all but fp enable bit 22970Sstevel@tonic-gate srlx %g2, PSR_FPRS_FEF_SHIFT, %g4 ! shift ef to V9 fprs.fef 22980Sstevel@tonic-gate wr %g0, %g4, %fprs ! write fprs 22990Sstevel@tonic-gate 23000Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 23010Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 23020Sstevel@tonic-gate ldn [%g2 + T_LWP], %g3 ! load klwp pointer 23030Sstevel@tonic-gate ldn [%g3 + LWP_FPU], %g2 ! get lwp_fpu pointer 23040Sstevel@tonic-gate stuw %g4, [%g2 + FPU_FPRS] ! write fef value to fpu_fprs 23050Sstevel@tonic-gate srlx %g4, 2, %g4 ! shift fef value to bit 0 23060Sstevel@tonic-gate stub %g4, [%g2 + FPU_EN] ! write fef value to fpu_en 23070Sstevel@tonic-gate FAST_TRAP_DONE 23080Sstevel@tonic-gate SET_SIZE(.setpsr) 23090Sstevel@tonic-gate 23100Sstevel@tonic-gate/* 23110Sstevel@tonic-gate * getlgrp 23120Sstevel@tonic-gate * get home lgrpid on which the calling thread is currently executing. 23130Sstevel@tonic-gate */ 23140Sstevel@tonic-gate .type .getlgrp, #function 23150Sstevel@tonic-gate.getlgrp: 23160Sstevel@tonic-gate ! Thanks for the incredibly helpful comments 23170Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 23180Sstevel@tonic-gate ld [%g1 + CPU_ID], %o0 ! load cpu_id 23190Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 23200Sstevel@tonic-gate ldn [%g2 + T_LPL], %g2 ! load lpl pointer 23210Sstevel@tonic-gate ld [%g2 + LPL_LGRPID], %g1 ! load lpl_lgrpid 23220Sstevel@tonic-gate sra %g1, 0, %o1 23230Sstevel@tonic-gate FAST_TRAP_DONE 23240Sstevel@tonic-gate SET_SIZE(.getlgrp) 23250Sstevel@tonic-gate 23260Sstevel@tonic-gate/* 23270Sstevel@tonic-gate * Entry for old 4.x trap (trap 0). 23280Sstevel@tonic-gate */ 23290Sstevel@tonic-gate ENTRY_NP(syscall_trap_4x) 23300Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 23310Sstevel@tonic-gate ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer 23320Sstevel@tonic-gate ldn [%g2 + T_LWP], %g2 ! load klwp pointer 23330Sstevel@tonic-gate ld [%g2 + PCB_TRAP0], %g2 ! lwp->lwp_pcb.pcb_trap0addr 23340Sstevel@tonic-gate brz,pn %g2, 1f ! has it been set? 23350Sstevel@tonic-gate st %l0, [%g1 + CPU_TMP1] ! delay - save some locals 23360Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 23370Sstevel@tonic-gate rdpr %tnpc, %l1 ! save old tnpc 23380Sstevel@tonic-gate wrpr %g0, %g2, %tnpc ! setup tnpc 23390Sstevel@tonic-gate 23400Sstevel@tonic-gate mov %g1, %l0 ! save CPU struct addr 23410Sstevel@tonic-gate wrpr %g0, 0, %gl 23420Sstevel@tonic-gate mov %l1, %g6 ! pass tnpc to user code in %g6 23430Sstevel@tonic-gate wrpr %g0, 1, %gl 23440Sstevel@tonic-gate ld [%l0 + CPU_TMP2], %l1 ! restore locals 23450Sstevel@tonic-gate ld [%l0 + CPU_TMP1], %l0 23460Sstevel@tonic-gate FAST_TRAP_DONE_CHK_INTR 23470Sstevel@tonic-gate1: 23480Sstevel@tonic-gate ! 23490Sstevel@tonic-gate ! check for old syscall mmap which is the only different one which 23500Sstevel@tonic-gate ! must be the same. Others are handled in the compatibility library. 23510Sstevel@tonic-gate ! 23520Sstevel@tonic-gate mov %g1, %l0 ! save CPU struct addr 23530Sstevel@tonic-gate wrpr %g0, 0, %gl 23540Sstevel@tonic-gate cmp %g1, OSYS_mmap ! compare to old 4.x mmap 23550Sstevel@tonic-gate movz %icc, SYS_mmap, %g1 23560Sstevel@tonic-gate wrpr %g0, 1, %gl 23570Sstevel@tonic-gate ld [%l0 + CPU_TMP1], %l0 23580Sstevel@tonic-gate SYSCALL(syscall_trap32) 23590Sstevel@tonic-gate SET_SIZE(syscall_trap_4x) 23600Sstevel@tonic-gate 23610Sstevel@tonic-gate/* 23620Sstevel@tonic-gate * Handler for software trap 9. 23630Sstevel@tonic-gate * Set trap0 emulation address for old 4.x system call trap. 23640Sstevel@tonic-gate * XXX - this should be a system call. 23650Sstevel@tonic-gate */ 23660Sstevel@tonic-gate ENTRY_NP(set_trap0_addr) 23670Sstevel@tonic-gate CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2 23680Sstevel@tonic-gate st %l0, [%g1 + CPU_TMP1] ! save some locals 23690Sstevel@tonic-gate st %l1, [%g1 + CPU_TMP2] 23700Sstevel@tonic-gate mov %g1, %l0 ! preserve CPU addr 23710Sstevel@tonic-gate wrpr %g0, 0, %gl 23720Sstevel@tonic-gate mov %g1, %l1 23730Sstevel@tonic-gate wrpr %g0, 1, %gl 23740Sstevel@tonic-gate ! cannot assume globals retained their values after increasing %gl 23750Sstevel@tonic-gate ldn [%l0 + CPU_THREAD], %g2 ! load thread pointer 23760Sstevel@tonic-gate ldn [%g2 + T_LWP], %g2 ! load klwp pointer 23770Sstevel@tonic-gate andn %l1, 3, %l1 ! force alignment 23780Sstevel@tonic-gate st %l1, [%g2 + PCB_TRAP0] ! lwp->lwp_pcb.pcb_trap0addr 23790Sstevel@tonic-gate ld [%l0 + CPU_TMP2], %l1 ! restore locals 23800Sstevel@tonic-gate ld [%l0 + CPU_TMP1], %l0 23810Sstevel@tonic-gate FAST_TRAP_DONE 23820Sstevel@tonic-gate SET_SIZE(set_trap0_addr) 23830Sstevel@tonic-gate 23840Sstevel@tonic-gate/* 23850Sstevel@tonic-gate * mmu_trap_tl1 23860Sstevel@tonic-gate * trap handler for unexpected mmu traps. 23870Sstevel@tonic-gate * simply checks if the trap was a user lddf/stdf alignment trap, in which 23880Sstevel@tonic-gate * case we go to fpu_trap or a user trap from the window handler, in which 23890Sstevel@tonic-gate * case we go save the state on the pcb. Otherwise, we go to ptl1_panic. 23900Sstevel@tonic-gate */ 23910Sstevel@tonic-gate .type mmu_trap_tl1, #function 23920Sstevel@tonic-gatemmu_trap_tl1: 23930Sstevel@tonic-gate#ifdef TRAPTRACE 23940Sstevel@tonic-gate TRACE_PTR(%g5, %g6) 2395*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g7) 23960Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_TICK]%asi 23970Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g5, %g6) 23980Sstevel@tonic-gate rdpr %tt, %g6 23990Sstevel@tonic-gate stha %g6, [%g5 + TRAP_ENT_TT]%asi 24000Sstevel@tonic-gate rdpr %tstate, %g6 24010Sstevel@tonic-gate stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi 24020Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 24030Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 24040Sstevel@tonic-gate rdpr %tpc, %g6 24050Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_TPC]%asi 24060Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g6) 24070Sstevel@tonic-gate ldx [%g6 + MMFSA_D_ADDR], %g6 24080Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F1]%asi ! MMU fault address 24090Sstevel@tonic-gate CPU_PADDR(%g7, %g6); 24100Sstevel@tonic-gate add %g7, CPU_TL1_HDLR, %g7 24110Sstevel@tonic-gate lda [%g7]ASI_MEM, %g6 24120Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F2]%asi 24130Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g6) 24140Sstevel@tonic-gate ldx [%g6 + MMFSA_D_TYPE], %g7 ! XXXQ should be a MMFSA_F_ constant? 24150Sstevel@tonic-gate ldx [%g6 + MMFSA_D_CTX], %g6 24160Sstevel@tonic-gate sllx %g6, SFSR_CTX_SHIFT, %g6 24170Sstevel@tonic-gate or %g6, %g7, %g6 24180Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F3]%asi ! MMU context/type 24190Sstevel@tonic-gate set 0xdeadbeef, %g6 24200Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F4]%asi 24210Sstevel@tonic-gate TRACE_NEXT(%g5, %g6, %g7) 24220Sstevel@tonic-gate#endif /* TRAPTRACE */ 24230Sstevel@tonic-gate CPU_PADDR(%g7, %g6); 24240Sstevel@tonic-gate add %g7, CPU_TL1_HDLR, %g7 ! %g7 = &cpu_m.tl1_hdlr (PA) 24250Sstevel@tonic-gate lda [%g7]ASI_MEM, %g6 24260Sstevel@tonic-gate brz,a,pt %g6, 1f 24270Sstevel@tonic-gate nop 24280Sstevel@tonic-gate sta %g0, [%g7]ASI_MEM 24290Sstevel@tonic-gate ! XXXQ need to setup registers for sfmmu_mmu_trap? 24300Sstevel@tonic-gate ba,a,pt %xcc, sfmmu_mmu_trap ! handle page faults 24310Sstevel@tonic-gate1: 24320Sstevel@tonic-gate rdpr %tpc, %g7 24330Sstevel@tonic-gate /* in user_rtt? */ 24340Sstevel@tonic-gate set rtt_fill_start, %g6 24350Sstevel@tonic-gate cmp %g7, %g6 24360Sstevel@tonic-gate blu,pn %xcc, 6f 24370Sstevel@tonic-gate .empty 24380Sstevel@tonic-gate set rtt_fill_end, %g6 24390Sstevel@tonic-gate cmp %g7, %g6 24400Sstevel@tonic-gate bgeu,pn %xcc, 6f 24410Sstevel@tonic-gate nop 24420Sstevel@tonic-gate set fault_rtt_fn1, %g7 24430Sstevel@tonic-gate ba,a 7f 24440Sstevel@tonic-gate6: 24450Sstevel@tonic-gate ! check to see if the trap pc is in a window spill/fill handling 24460Sstevel@tonic-gate rdpr %tpc, %g7 24470Sstevel@tonic-gate /* tpc should be in the trap table */ 24480Sstevel@tonic-gate set trap_table, %g6 24490Sstevel@tonic-gate cmp %g7, %g6 24500Sstevel@tonic-gate blu,a,pn %xcc, ptl1_panic 24510Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 24520Sstevel@tonic-gate set etrap_table, %g6 24530Sstevel@tonic-gate cmp %g7, %g6 24540Sstevel@tonic-gate bgeu,a,pn %xcc, ptl1_panic 24550Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 24560Sstevel@tonic-gate ! pc is inside the trap table, convert to trap type 24570Sstevel@tonic-gate srl %g7, 5, %g6 ! XXXQ need #define 24580Sstevel@tonic-gate and %g6, 0x1ff, %g6 ! XXXQ need #define 24590Sstevel@tonic-gate ! and check for a window trap type 24600Sstevel@tonic-gate and %g6, WTRAP_TTMASK, %g6 24610Sstevel@tonic-gate cmp %g6, WTRAP_TYPE 24620Sstevel@tonic-gate bne,a,pn %xcc, ptl1_panic 24630Sstevel@tonic-gate mov PTL1_BAD_MMUTRAP, %g1 24640Sstevel@tonic-gate andn %g7, WTRAP_ALIGN, %g7 /* 128 byte aligned */ 24650Sstevel@tonic-gate add %g7, WTRAP_FAULTOFF, %g7 24660Sstevel@tonic-gate 24670Sstevel@tonic-gate7: 24680Sstevel@tonic-gate ! Arguments are passed in the global set active after the 24690Sstevel@tonic-gate ! 'done' instruction. Before switching sets, must save 24700Sstevel@tonic-gate ! the calculated next pc 24710Sstevel@tonic-gate wrpr %g0, %g7, %tnpc 24720Sstevel@tonic-gate wrpr %g0, 1, %gl 24730Sstevel@tonic-gate rdpr %tt, %g5 2474526Sarao MMU_FAULT_STATUS_AREA(%g7) 24750Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 2476526Sarao be,pn %xcc, 1f 2477526Sarao ldx [%g7 + MMFSA_D_ADDR], %g6 2478526Sarao ldx [%g7 + MMFSA_D_CTX], %g7 2479526Sarao srlx %g6, MMU_PAGESHIFT, %g6 /* align address */ 24803687Sjb145095 cmp %g7, USER_CONTEXT_TYPE 2481526Sarao sllx %g6, MMU_PAGESHIFT, %g6 24823687Sjb145095 movgu %icc, USER_CONTEXT_TYPE, %g7 2483526Sarao or %g6, %g7, %g6 /* TAG_ACCESS */ 2484526Sarao1: 24850Sstevel@tonic-gate done 24860Sstevel@tonic-gate SET_SIZE(mmu_trap_tl1) 24870Sstevel@tonic-gate 24880Sstevel@tonic-gate/* 24890Sstevel@tonic-gate * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers. These 24900Sstevel@tonic-gate * traps are valid only when kmdb is loaded. When the debugger is active, 24910Sstevel@tonic-gate * the code below is rewritten to transfer control to the appropriate 24920Sstevel@tonic-gate * debugger entry points. 24930Sstevel@tonic-gate */ 24940Sstevel@tonic-gate .global kmdb_trap 24950Sstevel@tonic-gate .align 8 24960Sstevel@tonic-gatekmdb_trap: 24970Sstevel@tonic-gate ba,a trap_table0 24980Sstevel@tonic-gate jmp %g1 + 0 24990Sstevel@tonic-gate nop 25000Sstevel@tonic-gate 25010Sstevel@tonic-gate .global kmdb_trap_tl1 25020Sstevel@tonic-gate .align 8 25030Sstevel@tonic-gatekmdb_trap_tl1: 25040Sstevel@tonic-gate ba,a trap_table0 25050Sstevel@tonic-gate jmp %g1 + 0 25060Sstevel@tonic-gate nop 25070Sstevel@tonic-gate 25080Sstevel@tonic-gate/* 25090Sstevel@tonic-gate * This entry is copied from OBP's trap table during boot. 25100Sstevel@tonic-gate */ 25110Sstevel@tonic-gate .global obp_bpt 25120Sstevel@tonic-gate .align 8 25130Sstevel@tonic-gateobp_bpt: 25140Sstevel@tonic-gate NOT 25150Sstevel@tonic-gate 25160Sstevel@tonic-gate 25170Sstevel@tonic-gate 25180Sstevel@tonic-gate#ifdef TRAPTRACE 25190Sstevel@tonic-gate/* 25200Sstevel@tonic-gate * TRAPTRACE support. 25210Sstevel@tonic-gate * labels here are branched to with "rd %pc, %g7" in the delay slot. 25220Sstevel@tonic-gate * Return is done by "jmp %g7 + 4". 25230Sstevel@tonic-gate */ 25240Sstevel@tonic-gate 25250Sstevel@tonic-gatetrace_dmmu: 25260Sstevel@tonic-gate TRACE_PTR(%g3, %g6) 2527*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g5) 25280Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 25290Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g3, %g6) 25300Sstevel@tonic-gate rdpr %tt, %g6 25310Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi 25320Sstevel@tonic-gate rdpr %tstate, %g6 25330Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TSTATE]%asi 25340Sstevel@tonic-gate stna %sp, [%g3 + TRAP_ENT_SP]%asi 25350Sstevel@tonic-gate rdpr %tpc, %g6 25360Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_TPC]%asi 25370Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g6) 25380Sstevel@tonic-gate ldx [%g6 + MMFSA_D_ADDR], %g4 25390Sstevel@tonic-gate stxa %g4, [%g3 + TRAP_ENT_TR]%asi 25400Sstevel@tonic-gate ldx [%g6 + MMFSA_D_CTX], %g4 25410Sstevel@tonic-gate stxa %g4, [%g3 + TRAP_ENT_F1]%asi 25420Sstevel@tonic-gate ldx [%g6 + MMFSA_D_TYPE], %g4 25430Sstevel@tonic-gate stxa %g4, [%g3 + TRAP_ENT_F2]%asi 25440Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_F3]%asi 25450Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F4]%asi 25460Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g5) 25470Sstevel@tonic-gate jmp %g7 + 4 25480Sstevel@tonic-gate nop 25490Sstevel@tonic-gate 25500Sstevel@tonic-gatetrace_immu: 25510Sstevel@tonic-gate TRACE_PTR(%g3, %g6) 2552*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g5) 25530Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 25540Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g3, %g6) 25550Sstevel@tonic-gate rdpr %tt, %g6 25560Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi 25570Sstevel@tonic-gate rdpr %tstate, %g6 25580Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TSTATE]%asi 25590Sstevel@tonic-gate stna %sp, [%g3 + TRAP_ENT_SP]%asi 25600Sstevel@tonic-gate rdpr %tpc, %g6 25610Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_TPC]%asi 25620Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g6) 25630Sstevel@tonic-gate ldx [%g6 + MMFSA_I_ADDR], %g4 25640Sstevel@tonic-gate stxa %g4, [%g3 + TRAP_ENT_TR]%asi 25650Sstevel@tonic-gate ldx [%g6 + MMFSA_I_CTX], %g4 25660Sstevel@tonic-gate stxa %g4, [%g3 + TRAP_ENT_F1]%asi 25670Sstevel@tonic-gate ldx [%g6 + MMFSA_I_TYPE], %g4 25680Sstevel@tonic-gate stxa %g4, [%g3 + TRAP_ENT_F2]%asi 25690Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_F3]%asi 25700Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F4]%asi 25710Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g5) 25720Sstevel@tonic-gate jmp %g7 + 4 25730Sstevel@tonic-gate nop 25740Sstevel@tonic-gate 25750Sstevel@tonic-gatetrace_gen: 25760Sstevel@tonic-gate TRACE_PTR(%g3, %g6) 2577*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g5) 25780Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 25790Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g3, %g6) 25800Sstevel@tonic-gate rdpr %tt, %g6 25810Sstevel@tonic-gate stha %g6, [%g3 + TRAP_ENT_TT]%asi 25820Sstevel@tonic-gate rdpr %tstate, %g6 25830Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TSTATE]%asi 25840Sstevel@tonic-gate stna %sp, [%g3 + TRAP_ENT_SP]%asi 25850Sstevel@tonic-gate rdpr %tpc, %g6 25860Sstevel@tonic-gate stna %g6, [%g3 + TRAP_ENT_TPC]%asi 25870Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_TR]%asi 25880Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F1]%asi 25890Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F2]%asi 25900Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F3]%asi 25910Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F4]%asi 25920Sstevel@tonic-gate TRACE_NEXT(%g3, %g4, %g5) 25930Sstevel@tonic-gate jmp %g7 + 4 25940Sstevel@tonic-gate nop 25950Sstevel@tonic-gate 25960Sstevel@tonic-gatetrace_win: 25970Sstevel@tonic-gate TRACE_WIN_INFO(0, %l0, %l1, %l2) 25980Sstevel@tonic-gate ! Keep the locals as clean as possible, caller cleans %l4 25990Sstevel@tonic-gate clr %l2 26000Sstevel@tonic-gate clr %l1 26010Sstevel@tonic-gate jmp %l4 + 4 26020Sstevel@tonic-gate clr %l0 26030Sstevel@tonic-gate 26040Sstevel@tonic-gate/* 26050Sstevel@tonic-gate * Trace a tsb hit 26060Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered) 26070Sstevel@tonic-gate * g2 = tag access register (in) 26080Sstevel@tonic-gate * g3 - g4 = scratch (clobbered) 26090Sstevel@tonic-gate * g5 = tsbe data (in) 26100Sstevel@tonic-gate * g6 = scratch (clobbered) 26110Sstevel@tonic-gate * g7 = pc we jumped here from (in) 26120Sstevel@tonic-gate */ 26130Sstevel@tonic-gate 26140Sstevel@tonic-gate ! Do not disturb %g5, it will be used after the trace 26150Sstevel@tonic-gate ALTENTRY(trace_tsbhit) 26160Sstevel@tonic-gate TRACE_TSBHIT(0) 26170Sstevel@tonic-gate jmp %g7 + 4 26180Sstevel@tonic-gate nop 26190Sstevel@tonic-gate 26200Sstevel@tonic-gate/* 26210Sstevel@tonic-gate * Trace a TSB miss 26220Sstevel@tonic-gate * 26230Sstevel@tonic-gate * g1 = tsb8k pointer (in) 26240Sstevel@tonic-gate * g2 = tag access register (in) 26250Sstevel@tonic-gate * g3 = tsb4m pointer (in) 26260Sstevel@tonic-gate * g4 = tsbe tag (in/clobbered) 26270Sstevel@tonic-gate * g5 - g6 = scratch (clobbered) 26280Sstevel@tonic-gate * g7 = pc we jumped here from (in) 26290Sstevel@tonic-gate */ 26300Sstevel@tonic-gate .global trace_tsbmiss 26310Sstevel@tonic-gatetrace_tsbmiss: 26320Sstevel@tonic-gate membar #Sync 26330Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 26340Sstevel@tonic-gate flush %g6 26350Sstevel@tonic-gate TRACE_PTR(%g5, %g6) 26360Sstevel@tonic-gate stna %g2, [%g5 + TRAP_ENT_SP]%asi ! tag access 26370Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_F1]%asi ! XXX? tsb tag 2638*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) 2639*11172SHaik.Aftandilian@Sun.COM stxa %g6, [%g5 + TRAP_ENT_TICK]%asi 26400Sstevel@tonic-gate rdpr %tnpc, %g6 26410Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_F2]%asi 26420Sstevel@tonic-gate stna %g1, [%g5 + TRAP_ENT_F3]%asi ! tsb8k pointer 26430Sstevel@tonic-gate rdpr %tpc, %g6 26440Sstevel@tonic-gate stna %g6, [%g5 + TRAP_ENT_TPC]%asi 26450Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g5, %g6) 26460Sstevel@tonic-gate rdpr %tt, %g6 26470Sstevel@tonic-gate or %g6, TT_MMU_MISS, %g4 26480Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 2649526Sarao mov MMFSA_D_ADDR, %g4 26500Sstevel@tonic-gate cmp %g6, FAST_IMMU_MISS_TT 2651526Sarao move %xcc, MMFSA_I_ADDR, %g4 26520Sstevel@tonic-gate cmp %g6, T_INSTR_MMU_MISS 2653526Sarao move %xcc, MMFSA_I_ADDR, %g4 2654526Sarao MMU_FAULT_STATUS_AREA(%g6) 2655526Sarao ldx [%g6 + %g4], %g6 2656526Sarao stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! tag target 26573687Sjb145095 cmp %g4, MMFSA_D_ADDR 26583687Sjb145095 move %xcc, MMFSA_D_CTX, %g4 26593687Sjb145095 movne %xcc, MMFSA_I_CTX, %g4 26603687Sjb145095 MMU_FAULT_STATUS_AREA(%g6) 26613687Sjb145095 ldx [%g6 + %g4], %g6 26623687Sjb145095 stxa %g6, [%g5 + TRAP_ENT_F4]%asi ! context ID 26630Sstevel@tonic-gate stna %g3, [%g5 + TRAP_ENT_TR]%asi ! tsb4m pointer 26640Sstevel@tonic-gate TRACE_NEXT(%g5, %g4, %g6) 26650Sstevel@tonic-gate jmp %g7 + 4 26660Sstevel@tonic-gate nop 26670Sstevel@tonic-gate 26680Sstevel@tonic-gate/* 26690Sstevel@tonic-gate * g2 = tag access register (in) 26703687Sjb145095 * g3 = ctx type (0, 1 or 2) (in) (not used) 26710Sstevel@tonic-gate */ 26720Sstevel@tonic-gatetrace_dataprot: 26730Sstevel@tonic-gate membar #Sync 26740Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g6 26750Sstevel@tonic-gate flush %g6 26760Sstevel@tonic-gate TRACE_PTR(%g1, %g6) 2677*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) 26780Sstevel@tonic-gate stxa %g6, [%g1 + TRAP_ENT_TICK]%asi 26790Sstevel@tonic-gate rdpr %tpc, %g6 26800Sstevel@tonic-gate stna %g6, [%g1 + TRAP_ENT_TPC]%asi 26810Sstevel@tonic-gate rdpr %tstate, %g6 26820Sstevel@tonic-gate stxa %g6, [%g1 + TRAP_ENT_TSTATE]%asi 26830Sstevel@tonic-gate stna %g2, [%g1 + TRAP_ENT_SP]%asi ! tag access reg 26840Sstevel@tonic-gate stna %g0, [%g1 + TRAP_ENT_F1]%asi 26850Sstevel@tonic-gate stna %g0, [%g1 + TRAP_ENT_F2]%asi 26860Sstevel@tonic-gate stna %g0, [%g1 + TRAP_ENT_F3]%asi 26870Sstevel@tonic-gate stna %g0, [%g1 + TRAP_ENT_F4]%asi 26880Sstevel@tonic-gate TRACE_SAVE_TL_GL_REGS(%g1, %g6) 26890Sstevel@tonic-gate rdpr %tt, %g6 26900Sstevel@tonic-gate stha %g6, [%g1 + TRAP_ENT_TT]%asi 26913687Sjb145095 mov MMFSA_D_CTX, %g4 26923687Sjb145095 cmp %g6, FAST_IMMU_MISS_TT 26933687Sjb145095 move %xcc, MMFSA_I_CTX, %g4 26943687Sjb145095 cmp %g6, T_INSTR_MMU_MISS 26953687Sjb145095 move %xcc, MMFSA_I_CTX, %g4 26963687Sjb145095 MMU_FAULT_STATUS_AREA(%g6) 26973687Sjb145095 ldx [%g6 + %g4], %g6 26983687Sjb145095 stxa %g6, [%g1 + TRAP_ENT_TR]%asi ! context ID 26990Sstevel@tonic-gate TRACE_NEXT(%g1, %g4, %g5) 27000Sstevel@tonic-gate jmp %g7 + 4 27010Sstevel@tonic-gate nop 27020Sstevel@tonic-gate 27030Sstevel@tonic-gate#endif /* TRAPTRACE */ 27040Sstevel@tonic-gate 2705526Sarao/* 27061991Sheppo * Handle watchdog reset trap. Enable the MMU using the MMU_ENABLE 27071991Sheppo * HV service, which requires the return target to be specified as a VA 27081991Sheppo * since we are enabling the MMU. We set the target to ptl1_panic. 27091991Sheppo */ 27101991Sheppo 27111991Sheppo .type .watchdog_trap, #function 27121991Sheppo.watchdog_trap: 27131991Sheppo mov 1, %o0 27141991Sheppo setx ptl1_panic, %g2, %o1 27151991Sheppo mov MMU_ENABLE, %o5 27161991Sheppo ta FAST_TRAP 27171991Sheppo done 27181991Sheppo SET_SIZE(.watchdog_trap) 27191991Sheppo/* 2720526Sarao * synthesize for trap(): SFAR in %g2, SFSR in %g3 2721526Sarao */ 2722526Sarao .type .dmmu_exc_lddf_not_aligned, #function 27230Sstevel@tonic-gate.dmmu_exc_lddf_not_aligned: 27240Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g3) 27250Sstevel@tonic-gate ldx [%g3 + MMFSA_D_ADDR], %g2 27260Sstevel@tonic-gate /* Fault type not available in MMU fault status area */ 27270Sstevel@tonic-gate mov MMFSA_F_UNALIGN, %g1 27280Sstevel@tonic-gate ldx [%g3 + MMFSA_D_CTX], %g3 27290Sstevel@tonic-gate sllx %g3, SFSR_CTX_SHIFT, %g3 27300Sstevel@tonic-gate btst 1, %sp 27310Sstevel@tonic-gate bnz,pt %xcc, .lddf_exception_not_aligned 2732526Sarao or %g3, %g1, %g3 /* SFSR */ 27330Sstevel@tonic-gate ba,a,pt %xcc, .mmu_exception_not_aligned 2734526Sarao SET_SIZE(.dmmu_exc_lddf_not_aligned) 27350Sstevel@tonic-gate 2736526Sarao/* 2737526Sarao * synthesize for trap(): SFAR in %g2, SFSR in %g3 2738526Sarao */ 2739526Sarao .type .dmmu_exc_stdf_not_aligned, #function 27400Sstevel@tonic-gate.dmmu_exc_stdf_not_aligned: 27410Sstevel@tonic-gate MMU_FAULT_STATUS_AREA(%g3) 27420Sstevel@tonic-gate ldx [%g3 + MMFSA_D_ADDR], %g2 27430Sstevel@tonic-gate /* Fault type not available in MMU fault status area */ 27440Sstevel@tonic-gate mov MMFSA_F_UNALIGN, %g1 27450Sstevel@tonic-gate ldx [%g3 + MMFSA_D_CTX], %g3 27460Sstevel@tonic-gate sllx %g3, SFSR_CTX_SHIFT, %g3 27470Sstevel@tonic-gate btst 1, %sp 27480Sstevel@tonic-gate bnz,pt %xcc, .stdf_exception_not_aligned 2749526Sarao or %g3, %g1, %g3 /* SFSR */ 27500Sstevel@tonic-gate ba,a,pt %xcc, .mmu_exception_not_aligned 2751526Sarao SET_SIZE(.dmmu_exc_stdf_not_aligned) 27520Sstevel@tonic-gate 2753526Sarao .type .dmmu_exception, #function 2754526Sarao.dmmu_exception: 2755526Sarao MMU_FAULT_STATUS_AREA(%g3) 2756526Sarao ldx [%g3 + MMFSA_D_ADDR], %g2 2757526Sarao ldx [%g3 + MMFSA_D_TYPE], %g1 27583687Sjb145095 ldx [%g3 + MMFSA_D_CTX], %g4 2759526Sarao srlx %g2, MMU_PAGESHIFT, %g2 /* align address */ 2760526Sarao sllx %g2, MMU_PAGESHIFT, %g2 27613687Sjb145095 sllx %g4, SFSR_CTX_SHIFT, %g3 2762526Sarao or %g3, %g1, %g3 /* SFSR */ 27633687Sjb145095 cmp %g4, USER_CONTEXT_TYPE 27643687Sjb145095 movgeu %icc, USER_CONTEXT_TYPE, %g4 27653687Sjb145095 or %g2, %g4, %g2 /* TAG_ACCESS */ 2766526Sarao ba,pt %xcc, .mmu_exception_end 2767526Sarao mov T_DATA_EXCEPTION, %g1 2768526Sarao SET_SIZE(.dmmu_exception) 27690Sstevel@tonic-gate 27708803SJonathan.Haslam@Sun.COM .align 32 27718803SJonathan.Haslam@Sun.COM .global pil15_epilogue 27728803SJonathan.Haslam@Sun.COMpil15_epilogue: 27738803SJonathan.Haslam@Sun.COM ba pil_interrupt_common 27748803SJonathan.Haslam@Sun.COM nop 27758803SJonathan.Haslam@Sun.COM .align 32 27768803SJonathan.Haslam@Sun.COM 27770Sstevel@tonic-gate/* 27780Sstevel@tonic-gate * fast_trap_done, fast_trap_done_chk_intr: 27790Sstevel@tonic-gate * 27800Sstevel@tonic-gate * Due to the design of UltraSPARC pipeline, pending interrupts are not 27810Sstevel@tonic-gate * taken immediately after a RETRY or DONE instruction which causes IE to 27820Sstevel@tonic-gate * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed 27830Sstevel@tonic-gate * to execute first before taking any interrupts. If that instruction 27840Sstevel@tonic-gate * results in other traps, and if the corresponding trap handler runs 27850Sstevel@tonic-gate * entirely at TL=1 with interrupts disabled, then pending interrupts 27860Sstevel@tonic-gate * won't be taken until after yet another instruction following the %tpc 27870Sstevel@tonic-gate * or %tnpc. 27880Sstevel@tonic-gate * 27890Sstevel@tonic-gate * A malicious user program can use this feature to block out interrupts 27900Sstevel@tonic-gate * for extended durations, which can result in send_mondo_timeout kernel 27910Sstevel@tonic-gate * panic. 27920Sstevel@tonic-gate * 27930Sstevel@tonic-gate * This problem is addressed by servicing any pending interrupts via 27940Sstevel@tonic-gate * sys_trap before returning back to the user mode from a fast trap 27950Sstevel@tonic-gate * handler. The "done" instruction within a fast trap handler, which 27960Sstevel@tonic-gate * runs entirely at TL=1 with interrupts disabled, is replaced with the 27970Sstevel@tonic-gate * FAST_TRAP_DONE macro, which branches control to this fast_trap_done 27980Sstevel@tonic-gate * entry point. 27990Sstevel@tonic-gate * 28000Sstevel@tonic-gate * We check for any pending interrupts here and force a sys_trap to 28010Sstevel@tonic-gate * service those interrupts, if any. To minimize overhead, pending 28020Sstevel@tonic-gate * interrupts are checked if the %tpc happens to be at 16K boundary, 28030Sstevel@tonic-gate * which allows a malicious program to execute at most 4K consecutive 28040Sstevel@tonic-gate * instructions before we service any pending interrupts. If a worst 28050Sstevel@tonic-gate * case fast trap handler takes about 2 usec, then interrupts will be 28060Sstevel@tonic-gate * blocked for at most 8 msec, less than a clock tick. 28070Sstevel@tonic-gate * 28080Sstevel@tonic-gate * For the cases where we don't know if the %tpc will cross a 16K 28090Sstevel@tonic-gate * boundary, we can't use the above optimization and always process 28100Sstevel@tonic-gate * any pending interrupts via fast_frap_done_chk_intr entry point. 28110Sstevel@tonic-gate * 28120Sstevel@tonic-gate * Entry Conditions: 28130Sstevel@tonic-gate * %pstate am:0 priv:1 ie:0 28140Sstevel@tonic-gate * globals are AG (not normal globals) 28150Sstevel@tonic-gate */ 28160Sstevel@tonic-gate 28170Sstevel@tonic-gate .global fast_trap_done, fast_trap_done_chk_intr 28180Sstevel@tonic-gatefast_trap_done: 28190Sstevel@tonic-gate rdpr %tpc, %g5 28200Sstevel@tonic-gate sethi %hi(0xffffc000), %g6 ! 1's complement of 0x3fff 28210Sstevel@tonic-gate andncc %g5, %g6, %g0 ! check lower 14 bits of %tpc 28220Sstevel@tonic-gate bz,pn %icc, 1f ! branch if zero (lower 32 bits only) 28230Sstevel@tonic-gate nop 28240Sstevel@tonic-gate done 28250Sstevel@tonic-gate 28260Sstevel@tonic-gatefast_trap_done_chk_intr: 28270Sstevel@tonic-gate1: rd SOFTINT, %g6 28280Sstevel@tonic-gate brnz,pn %g6, 2f ! branch if any pending intr 28290Sstevel@tonic-gate nop 28300Sstevel@tonic-gate done 28310Sstevel@tonic-gate 28320Sstevel@tonic-gate2: 28330Sstevel@tonic-gate /* 28340Sstevel@tonic-gate * We get here if there are any pending interrupts. 28350Sstevel@tonic-gate * Adjust %tpc/%tnpc as we'll be resuming via "retry" 28360Sstevel@tonic-gate * instruction. 28370Sstevel@tonic-gate */ 28380Sstevel@tonic-gate rdpr %tnpc, %g5 28390Sstevel@tonic-gate wrpr %g0, %g5, %tpc 28400Sstevel@tonic-gate add %g5, 4, %g5 28410Sstevel@tonic-gate wrpr %g0, %g5, %tnpc 28420Sstevel@tonic-gate 28430Sstevel@tonic-gate /* 28440Sstevel@tonic-gate * Force a dummy sys_trap call so that interrupts can be serviced. 28450Sstevel@tonic-gate */ 28460Sstevel@tonic-gate set fast_trap_dummy_call, %g1 28470Sstevel@tonic-gate ba,pt %xcc, sys_trap 28480Sstevel@tonic-gate mov -1, %g4 28490Sstevel@tonic-gate 28500Sstevel@tonic-gatefast_trap_dummy_call: 28510Sstevel@tonic-gate retl 28520Sstevel@tonic-gate nop 28530Sstevel@tonic-gate 28544127Sedp/* 28554141Sedp * Currently the brand syscall interposition code is not enabled by 28564141Sedp * default. Instead, when a branded zone is first booted the brand 28574141Sedp * infrastructure will patch the trap table so that the syscall 28584141Sedp * entry points are redirected to syscall_wrapper32 and syscall_wrapper 28594141Sedp * for ILP32 and LP64 syscalls respectively. this is done in 28604141Sedp * brand_plat_interposition_enable(). Note that the syscall wrappers 28614141Sedp * below do not collect any trap trace data since the syscall hot patch 28624141Sedp * points are reached after trap trace data has already been collected. 28634127Sedp */ 28644127Sedp#define BRAND_CALLBACK(callback_id) \ 28654127Sedp CPU_ADDR(%g2, %g1) /* load CPU struct addr to %g2 */ ;\ 28664127Sedp ldn [%g2 + CPU_THREAD], %g3 /* load thread pointer */ ;\ 28674127Sedp ldn [%g3 + T_PROCP], %g3 /* get proc pointer */ ;\ 28684127Sedp ldn [%g3 + P_BRAND], %g3 /* get brand pointer */ ;\ 28694127Sedp brz %g3, 1f /* No brand? No callback. */ ;\ 28704127Sedp nop ;\ 28714127Sedp ldn [%g3 + B_MACHOPS], %g3 /* get machops list */ ;\ 28724127Sedp ldn [%g3 + (callback_id << 3)], %g3 ;\ 28734127Sedp brz %g3, 1f ;\ 28744127Sedp /* \ 28754127Sedp * This isn't pretty. We want a low-latency way for the callback \ 28764127Sedp * routine to decline to do anything. We just pass in an address \ 28774127Sedp * the routine can directly jmp back to, pretending that nothing \ 28784127Sedp * has happened. \ 28794127Sedp * \ 28804127Sedp * %g1: return address (where the brand handler jumps back to) \ 28814127Sedp * %g2: address of CPU structure \ 28824127Sedp * %g3: address of brand handler (where we will jump to) \ 28834127Sedp */ \ 28844127Sedp mov %pc, %g1 ;\ 28854127Sedp add %g1, 16, %g1 ;\ 28864127Sedp jmp %g3 ;\ 28874127Sedp nop ;\ 28884127Sedp1: 28894127Sedp 28904127Sedp ENTRY_NP(syscall_wrapper32) 28914127Sedp BRAND_CALLBACK(BRAND_CB_SYSCALL32) 28924127Sedp SYSCALL_NOTT(syscall_trap32) 28934127Sedp SET_SIZE(syscall_wrapper32) 28944127Sedp 28954127Sedp ENTRY_NP(syscall_wrapper) 28964127Sedp BRAND_CALLBACK(BRAND_CB_SYSCALL) 28974127Sedp SYSCALL_NOTT(syscall_trap) 28984127Sedp SET_SIZE(syscall_wrapper) 28994127Sedp 29000Sstevel@tonic-gate#endif /* lint */ 2901