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 52310Shyw * Common Development and Distribution License (the "License"). 62310Shyw * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate/* 22*11172SHaik.Aftandilian@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate#if defined(lint) 270Sstevel@tonic-gate#include <sys/types.h> 280Sstevel@tonic-gate#include <sys/thread.h> 290Sstevel@tonic-gate#else /* lint */ 300Sstevel@tonic-gate#include "assym.h" 310Sstevel@tonic-gate#endif /* lint */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate#include <sys/asm_linkage.h> 340Sstevel@tonic-gate#include <sys/machthread.h> 350Sstevel@tonic-gate#include <sys/machcpuvar.h> 360Sstevel@tonic-gate#include <sys/mmu.h> 370Sstevel@tonic-gate#include <sys/intreg.h> 380Sstevel@tonic-gate#include <sys/dmv.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate#ifdef TRAPTRACE 410Sstevel@tonic-gate#include <sys/traptrace.h> 420Sstevel@tonic-gate#endif /* TRAPTRACE */ 430Sstevel@tonic-gate 440Sstevel@tonic-gate 450Sstevel@tonic-gate#if defined(lint) 460Sstevel@tonic-gate 470Sstevel@tonic-gatevoid 480Sstevel@tonic-gatevec_interrupt(void) 490Sstevel@tonic-gate{} 500Sstevel@tonic-gate 510Sstevel@tonic-gate#else /* lint */ 520Sstevel@tonic-gate 530Sstevel@tonic-gatevec_uiii_irdr_tab: 540Sstevel@tonic-gate .byte UIII_IRDR_0, UIII_IRDR_1, UIII_IRDR_2, UIII_IRDR_3 550Sstevel@tonic-gate .byte UIII_IRDR_4, UIII_IRDR_5, UIII_IRDR_6, UIII_IRDR_7 560Sstevel@tonic-gate 570Sstevel@tonic-gate/* 580Sstevel@tonic-gate * (TT 0x60, TL>0) Interrupt Vector Handler 590Sstevel@tonic-gate * Globals are the Interrupt Globals. 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate ENTRY_NP(vec_interrupt) 620Sstevel@tonic-gate ! 630Sstevel@tonic-gate ! Load the interrupt receive data register 0. 640Sstevel@tonic-gate ! It could be a fast trap handler address (pc > KERNELBASE) at TL>0 650Sstevel@tonic-gate ! or an interrupt number. 660Sstevel@tonic-gate ! 670Sstevel@tonic-gate mov IRDR_0, %g2 680Sstevel@tonic-gate ldxa [%g2]ASI_INTR_RECEIVE, %g5 ! %g5 = PC or Interrupt Number 690Sstevel@tonic-gate 700Sstevel@tonic-gate ! If the high bit of IRDR_0 is set, then this is a 710Sstevel@tonic-gate ! data bearing mondo vector. 720Sstevel@tonic-gate brlz,pt %g5, dmv_vector 730Sstevel@tonic-gate .empty 740Sstevel@tonic-gate 750Sstevel@tonic-gate 760Sstevel@tonic-gatevec_interrupt_resume: 770Sstevel@tonic-gate set KERNELBASE, %g4 780Sstevel@tonic-gate cmp %g5, %g4 790Sstevel@tonic-gate bl,a,pt %xcc, 0f ! an interrupt number found 800Sstevel@tonic-gate nop 810Sstevel@tonic-gate ! 820Sstevel@tonic-gate ! intercept OBP xcalls and set PCONTEXT=0 830Sstevel@tonic-gate ! 840Sstevel@tonic-gate set _end, %g4 ! _end is highest kernel address 850Sstevel@tonic-gate cmp %g5, %g4 860Sstevel@tonic-gate bl,a,pt %xcc, 7f 870Sstevel@tonic-gate nop 885584Sjimand 895584Sjimand#ifndef _OPL 900Sstevel@tonic-gate mov MMU_PCONTEXT, %g1 910Sstevel@tonic-gate ldxa [%g1]ASI_DMMU, %g1 920Sstevel@tonic-gate srlx %g1, CTXREG_NEXT_SHIFT, %g3 930Sstevel@tonic-gate brz,pt %g3, 7f ! nucleus pgsz is 0, no problem 940Sstevel@tonic-gate sllx %g3, CTXREG_NEXT_SHIFT, %g3 950Sstevel@tonic-gate set CTXREG_CTX_MASK, %g4 ! check Pcontext 960Sstevel@tonic-gate btst %g4, %g1 970Sstevel@tonic-gate bz,a,pt %xcc, 6f 980Sstevel@tonic-gate clr %g3 ! kernel: PCONTEXT=0 990Sstevel@tonic-gate xor %g3, %g1, %g3 ! user: clr N_pgsz0/1 bits 1000Sstevel@tonic-gate6: 1010Sstevel@tonic-gate set DEMAP_ALL_TYPE, %g1 1020Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 1030Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 1040Sstevel@tonic-gate mov MMU_PCONTEXT, %g1 1050Sstevel@tonic-gate stxa %g3, [%g1]ASI_DMMU 1060Sstevel@tonic-gate membar #Sync 1070Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g1 1080Sstevel@tonic-gate flush %g1 ! flush required by immu 1095584Sjimand#endif /* _OPL */ 1105584Sjimand 1110Sstevel@tonic-gate7: 1120Sstevel@tonic-gate ! 1130Sstevel@tonic-gate ! Cross-trap request case 1140Sstevel@tonic-gate ! 1150Sstevel@tonic-gate ! Load interrupt receive data registers 1 and 2 to fetch 1160Sstevel@tonic-gate ! the arguments for the fast trap handler. 1170Sstevel@tonic-gate ! 1180Sstevel@tonic-gate ! Register usage: 1190Sstevel@tonic-gate ! g5: TL>0 handler 1200Sstevel@tonic-gate ! g1: arg1 1210Sstevel@tonic-gate ! g2: arg2 1220Sstevel@tonic-gate ! g3: arg3 1230Sstevel@tonic-gate ! g4: arg4 1240Sstevel@tonic-gate ! 1250Sstevel@tonic-gate mov IRDR_1, %g2 1260Sstevel@tonic-gate ldxa [%g2]ASI_INTR_RECEIVE, %g1 1270Sstevel@tonic-gate mov IRDR_2, %g2 1280Sstevel@tonic-gate ldxa [%g2]ASI_INTR_RECEIVE, %g2 1290Sstevel@tonic-gate#ifdef TRAPTRACE 1300Sstevel@tonic-gate TRACE_PTR(%g4, %g6) 131*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g3) 1320Sstevel@tonic-gate stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 1330Sstevel@tonic-gate rdpr %tl, %g6 1340Sstevel@tonic-gate stha %g6, [%g4 + TRAP_ENT_TL]%asi 1350Sstevel@tonic-gate rdpr %tt, %g6 1360Sstevel@tonic-gate stha %g6, [%g4 + TRAP_ENT_TT]%asi 1370Sstevel@tonic-gate rdpr %tpc, %g6 1380Sstevel@tonic-gate stna %g6, [%g4 + TRAP_ENT_TPC]%asi 1390Sstevel@tonic-gate rdpr %tstate, %g6 1400Sstevel@tonic-gate stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 1410Sstevel@tonic-gate stna %sp, [%g4 + TRAP_ENT_SP]%asi 1420Sstevel@tonic-gate stna %g5, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 1430Sstevel@tonic-gate stxa %g1, [%g4 + TRAP_ENT_F1]%asi 1440Sstevel@tonic-gate stxa %g2, [%g4 + TRAP_ENT_F3]%asi 1450Sstevel@tonic-gate stxa %g0, [%g4 + TRAP_ENT_F2]%asi 1460Sstevel@tonic-gate stxa %g0, [%g4 + TRAP_ENT_F4]%asi 1470Sstevel@tonic-gate TRACE_NEXT(%g4, %g6, %g3) 1480Sstevel@tonic-gate#endif /* TRAPTRACE */ 1490Sstevel@tonic-gate stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit 1500Sstevel@tonic-gate membar #Sync 1510Sstevel@tonic-gate#ifdef SF_ERRATA_51 1520Sstevel@tonic-gate ba,pt %icc, 1f 1530Sstevel@tonic-gate nop 1540Sstevel@tonic-gate .align 32 1550Sstevel@tonic-gate1: jmp %g5 ! call the fast trap handler 1560Sstevel@tonic-gate nop 1570Sstevel@tonic-gate#else 1580Sstevel@tonic-gate jmp %g5 1590Sstevel@tonic-gate nop 1600Sstevel@tonic-gate#endif /* SF_ERRATA_51 */ 1610Sstevel@tonic-gate /* Never Reached */ 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate0: 1640Sstevel@tonic-gate ! We have an interrupt number. 1650Sstevel@tonic-gate ! 1660Sstevel@tonic-gate ! Register usage: 1670Sstevel@tonic-gate ! %g5 - inum 1680Sstevel@tonic-gate ! %g1 - temp 1690Sstevel@tonic-gate ! 1700Sstevel@tonic-gate ! We don't bother to verify that the received inum is valid (it should 1712973Sgovinda ! be < MAXIVNUM) since setvecint_tl1 will do that for us. 1720Sstevel@tonic-gate ! 1730Sstevel@tonic-gate ! clear BUSY bit 1740Sstevel@tonic-gate ! 1750Sstevel@tonic-gate stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS 1760Sstevel@tonic-gate membar #Sync 1770Sstevel@tonic-gate 1782973Sgovinda ! setvecint_tl1 will do all the work, and finish with a retry 1790Sstevel@tonic-gate ! 1802973Sgovinda ba,pt %xcc, setvecint_tl1 1812973Sgovinda mov %g5, %g1 ! setvecint_tl1 expects inum in %g1 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate /* Never Reached */ 1840Sstevel@tonic-gate SET_SIZE(vec_interrupt) 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate! 1880Sstevel@tonic-gate! See usr/src/uts/sun4u/sys/dmv.h for the Databearing Mondo Vector 1890Sstevel@tonic-gate! interrupt format 1900Sstevel@tonic-gate! 1910Sstevel@tonic-gate! Inputs: 1920Sstevel@tonic-gate! g1: value of ASI_INTR_RECEIVE_STATUS 1930Sstevel@tonic-gate! g5: word 0 of the interrupt data 1940Sstevel@tonic-gate! Register use: 1950Sstevel@tonic-gate! g2: dmv inum 1960Sstevel@tonic-gate! g3: scratch 1970Sstevel@tonic-gate! g4: pointer to dmv_dispatch_table 1980Sstevel@tonic-gate! g6: handler pointer from dispatch table 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate DGDEF(dmv_spurious_cnt) 2020Sstevel@tonic-gate .word 0 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate ENTRY_NP(dmv_vector) 2050Sstevel@tonic-gate srlx %g5, DMV_INUM_SHIFT, %g2 2060Sstevel@tonic-gate set DMV_INUM_MASK, %g3 2070Sstevel@tonic-gate and %g2, %g3, %g2 ! %g2 = inum 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate set dmv_totalints, %g3 2100Sstevel@tonic-gate ld [%g3], %g3 2110Sstevel@tonic-gate cmp %g2, %g3 2120Sstevel@tonic-gate bge,pn %xcc, 2f ! inum >= dmv_totalints 2130Sstevel@tonic-gate nop 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate set dmv_dispatch_table, %g3 2160Sstevel@tonic-gate ldn [%g3], %g4 2170Sstevel@tonic-gate brz,pn %g4, 2f 2180Sstevel@tonic-gate sll %g2, DMV_DISP_SHIFT, %g3 ! %g3 = inum*sizeof(struct dmv_disp) 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate add %g4, %g3, %g4 ! %g4 = &dmv_dispatch_table[inum] 2210Sstevel@tonic-gate#if (DMV_FUNC != 0) || (DMV_ARG != 8) 2220Sstevel@tonic-gate#error "DMV_FUNC or DMV_SIZE has changed" 2230Sstevel@tonic-gate#endif 2240Sstevel@tonic-gate ldda [%g4]ASI_NQUAD_LD, %g2 ! %g2=handler %g3=argument 2250Sstevel@tonic-gate mov %g3, %g1 2260Sstevel@tonic-gate brz,pn %g2, 2f 2270Sstevel@tonic-gate nop 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate ! we have a handler, so call it 2300Sstevel@tonic-gate ! On entry to the handler, the %g registers are set as follows: 2310Sstevel@tonic-gate ! 2320Sstevel@tonic-gate ! %g1 The argument (arg) passed to dmv_add_intr(). 2330Sstevel@tonic-gate ! %g2 Word 0 of the incoming mondo vector. 2340Sstevel@tonic-gate ! 2350Sstevel@tonic-gate jmp %g2 2360Sstevel@tonic-gate mov %g5, %g2 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate ! No handler was listed in the table, so just record it 2390Sstevel@tonic-gate ! as an error condition and continue. There is a race 2400Sstevel@tonic-gate ! window here updating the counter, but that's ok since 2410Sstevel@tonic-gate ! just knowing that spurious interrupts happened is enough, 2420Sstevel@tonic-gate ! we probably won't need to know exactly how many. 2430Sstevel@tonic-gate2: 2440Sstevel@tonic-gate set dmv_spurious_cnt, %g1 2450Sstevel@tonic-gate ld [%g1], %g2 2460Sstevel@tonic-gate inc %g2 2470Sstevel@tonic-gate ba,pt %xcc,3f 2480Sstevel@tonic-gate st %g2, [%g1] 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate ! When the handler's processing (which should be as quick as 2510Sstevel@tonic-gate ! possible) is complete, the handler must exit by jumping to 2520Sstevel@tonic-gate ! the label dmv_finish_intr. The contents of %g1 at this time 2530Sstevel@tonic-gate ! determine whether a software interrupt will be issued, as 2540Sstevel@tonic-gate ! follows: 2550Sstevel@tonic-gate ! 2560Sstevel@tonic-gate ! If %g1 is less than zero, no interrupt will be queued. 2570Sstevel@tonic-gate ! Otherwise, %g1 will be used as the interrupt number 2580Sstevel@tonic-gate ! to simulate; this means that the behavior of the 2590Sstevel@tonic-gate ! interrupt system will be exactly that which would have 2600Sstevel@tonic-gate ! occurred if the first word of the incoming interrupt 2610Sstevel@tonic-gate ! vector had contained the contents of %g1. 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate ENTRY_NP(dmv_finish_intr) 2640Sstevel@tonic-gate brlz,pn %g1,3f 2650Sstevel@tonic-gate nop 2660Sstevel@tonic-gate ! generate an interrupt based on the contents of %g1 2670Sstevel@tonic-gate ba,pt %xcc,vec_interrupt_resume 2680Sstevel@tonic-gate mov %g1, %g5 2690Sstevel@tonic-gate ! We are done 2700Sstevel@tonic-gate3: 2710Sstevel@tonic-gate stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the busy bit 2720Sstevel@tonic-gate retry 2730Sstevel@tonic-gate SET_SIZE(dmv_vector) 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate#endif /* lint */ 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate#if defined(lint) 2780Sstevel@tonic-gate 2790Sstevel@tonic-gatevoid 2800Sstevel@tonic-gatevec_intr_spurious(void) 2810Sstevel@tonic-gate{} 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate#else /* lint */ 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate DGDEF(vec_spurious_cnt) 2860Sstevel@tonic-gate .word 0 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate ENTRY_NP(vec_intr_spurious) 2890Sstevel@tonic-gate sethi %hi(vec_spurious_cnt), %g2 2900Sstevel@tonic-gate ld [%g2 + %lo(vec_spurious_cnt)], %g2 2910Sstevel@tonic-gate#ifdef TRAPTRACE 2920Sstevel@tonic-gate TRACE_PTR(%g4, %g6) 293*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g3) 2940Sstevel@tonic-gate stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 2950Sstevel@tonic-gate rdpr %tl, %g6 2960Sstevel@tonic-gate stha %g6, [%g4 + TRAP_ENT_TL]%asi 2970Sstevel@tonic-gate rdpr %tt, %g6 2980Sstevel@tonic-gate or %g6, TT_SPURIOUS_INT, %g6 2990Sstevel@tonic-gate stha %g6, [%g4 + TRAP_ENT_TT]%asi 3000Sstevel@tonic-gate rdpr %tpc, %g6 3010Sstevel@tonic-gate stna %g6, [%g4 + TRAP_ENT_TPC]%asi 3020Sstevel@tonic-gate rdpr %tstate, %g6 3030Sstevel@tonic-gate stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 3040Sstevel@tonic-gate stna %sp, [%g4 + TRAP_ENT_SP]%asi 3050Sstevel@tonic-gate stna %g1, [%g4 + TRAP_ENT_TR]%asi ! irsr 3060Sstevel@tonic-gate stna %g2, [%g4 + TRAP_ENT_F1]%asi 3070Sstevel@tonic-gate ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 3080Sstevel@tonic-gate stxa %g5, [%g4 + TRAP_ENT_F2]%asi 3090Sstevel@tonic-gate stxa %g0, [%g4 + TRAP_ENT_F4]%asi 3100Sstevel@tonic-gate TRACE_NEXT(%g4, %g6, %g3) 3110Sstevel@tonic-gate#endif /* TRAPTRACE */ 3120Sstevel@tonic-gate cmp %g2, 16 3130Sstevel@tonic-gate bl,a,pt %xcc, 1f 3140Sstevel@tonic-gate inc %g2 3150Sstevel@tonic-gate ! 3160Sstevel@tonic-gate ! prepare for sys_trap() 3170Sstevel@tonic-gate ! %g1 - sys_tl1_panic 3180Sstevel@tonic-gate ! %g2 - panic message 3190Sstevel@tonic-gate ! %g4 - current pil 3200Sstevel@tonic-gate ! 3212310Shyw#ifdef CLEAR_INTR_BUSYBIT_ON_SPURIOUS 3222310Shyw /* 3232310Shyw * Certain processors (OPL) need to explicitly 3242310Shyw * clear the intr busy bit even though it is 3252310Shyw * not visibly set (spurious intrs) 3262310Shyw */ 3272310Shyw stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit 3282310Shyw membar #Sync 3292310Shyw#endif /* CLEAR_INTR_BUSYBIT_ON_SPURIOUS */ 3300Sstevel@tonic-gate sub %g0, 1, %g4 3310Sstevel@tonic-gate set _not_ready, %g2 3320Sstevel@tonic-gate sethi %hi(sys_tl1_panic), %g1 3330Sstevel@tonic-gate ba,pt %xcc, sys_trap 3340Sstevel@tonic-gate or %g1, %lo(sys_tl1_panic), %g1 3350Sstevel@tonic-gate ! 3360Sstevel@tonic-gate1: sethi %hi(vec_spurious_cnt), %g1 3370Sstevel@tonic-gate st %g2, [%g1 + %lo(vec_spurious_cnt)] 3380Sstevel@tonic-gate retry 3390Sstevel@tonic-gate SET_SIZE(vec_intr_spurious) 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate_not_ready: .asciz "Interrupt Vector Receive Register not READY" 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate#endif /* lint */ 344