trap_subr64.S revision 95719
195719Sbenno/* $FreeBSD: head/sys/powerpc/aim/trap_subr.S 95719 2002-04-29 12:14:31Z benno $ */ 295719Sbenno/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ 395719Sbenno 495719Sbenno/* 595719Sbenno * Copyright (C) 1995, 1996 Wolfgang Solfrank. 695719Sbenno * Copyright (C) 1995, 1996 TooLs GmbH. 795719Sbenno * All rights reserved. 895719Sbenno * 995719Sbenno * Redistribution and use in source and binary forms, with or without 1095719Sbenno * modification, are permitted provided that the following conditions 1195719Sbenno * are met: 1295719Sbenno * 1. Redistributions of source code must retain the above copyright 1395719Sbenno * notice, this list of conditions and the following disclaimer. 1495719Sbenno * 2. Redistributions in binary form must reproduce the above copyright 1595719Sbenno * notice, this list of conditions and the following disclaimer in the 1695719Sbenno * documentation and/or other materials provided with the distribution. 1795719Sbenno * 3. All advertising materials mentioning features or use of this software 1895719Sbenno * must display the following acknowledgement: 1995719Sbenno * This product includes software developed by TooLs GmbH. 2095719Sbenno * 4. The name of TooLs GmbH may not be used to endorse or promote products 2195719Sbenno * derived from this software without specific prior written permission. 2295719Sbenno * 2395719Sbenno * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 2495719Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2595719Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2695719Sbenno * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2795719Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2895719Sbenno * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2995719Sbenno * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 3095719Sbenno * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 3195719Sbenno * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 3295719Sbenno * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3395719Sbenno */ 3495719Sbenno 3595719Sbenno/* 3695719Sbenno * NOTICE: This is not a standalone file. to use it, #include it in 3795719Sbenno * your port's locore.S, like so: 3895719Sbenno * 3995719Sbenno * #include <powerpc/powerpc/trap_subr.S> 4095719Sbenno */ 4195719Sbenno 4295719Sbenno/* 4395719Sbenno * XXX Fake AST trap vector. This is here until we work out how to safely 4495719Sbenno * remove the AST code. 4595719Sbenno */ 4695719Sbenno#define EXC_AST 0x3000 4795719Sbenno .data 4895719Sbenno .align 4 4995719Sbennoastpending: 5095719Sbenno .long 0 5195719Sbenno 5295719Sbenno/* 5395719Sbenno * Data used during primary/secondary traps/interrupts 5495719Sbenno */ 5595719Sbenno#define tempsave EXC_MCHK+0xe0 /* primary save area for trap handling */ 5695719Sbenno#define disisave EXC_DSI+0xe0 /* primary save area for dsi/isi traps */ 5795719Sbenno 5895719Sbenno/* 5995719Sbenno * XXX Interrupt and spill stacks need to be per-CPU. 6095719Sbenno */ 6195719Sbenno .data 6295719Sbenno .align 4 6395719Sbennointstk: 6495719Sbenno .space INTSTK /* interrupt stack */ 6595719Sbenno 6695719SbennoGLOBAL(intr_depth) 6795719Sbenno .long -1 /* in-use marker */ 6895719Sbenno 6995719Sbenno .comm spillstk,SPILLSTK,8 7095719Sbenno 7195719Sbenno/* 7295719Sbenno * This code gets copied to all the trap vectors 7395719Sbenno * (except ISI/DSI, ALI, the interrupts, and possibly the debugging 7495719Sbenno * traps when using IPKDB). 7595719Sbenno */ 7695719Sbenno .text 7795719Sbenno .globl _C_LABEL(trapcode),_C_LABEL(trapsize) 7895719Sbenno_C_LABEL(trapcode): 7995719Sbenno mtsprg 1,1 /* save SP */ 8095719Sbenno stmw 28,tempsave(0) /* free r28-r31 */ 8195719Sbenno mflr 28 /* save LR */ 8295719Sbenno mfcr 29 /* save CR */ 8395719Sbenno/* Test whether we already had PR set */ 8495719Sbenno mfsrr1 31 8595719Sbenno mtcr 31 8695719Sbenno bc 4,17,1f /* branch if PSL_PR is clear */ 8795719Sbenno mfsprg 31,0 8895719Sbenno lwz 1,PC_CURPCB(31) 8995719Sbenno addi 1,1,USPACE /* stack is top of user struct */ 9095719Sbenno1: 9195719Sbenno bla s_trap 9295719Sbenno_C_LABEL(trapsize) = .-_C_LABEL(trapcode) 9395719Sbenno 9495719Sbenno/* 9595719Sbenno * For ALI: has to save DSISR and DAR 9695719Sbenno */ 9795719Sbenno .globl _C_LABEL(alitrap),_C_LABEL(alisize) 9895719Sbenno_C_LABEL(alitrap): 9995719Sbenno mtsprg 1,1 /* save SP */ 10095719Sbenno stmw 28,tempsave(0) /* free r28-r31 */ 10195719Sbenno mfdar 30 10295719Sbenno mfdsisr 31 10395719Sbenno stmw 30,tempsave+16(0) 10495719Sbenno mflr 28 /* save LR */ 10595719Sbenno mfcr 29 /* save CR */ 10695719Sbenno/* Test whether we already had PR set */ 10795719Sbenno mfsrr1 31 10895719Sbenno mtcr 31 10995719Sbenno bc 4,17,1f /* branch if PSL_PR is clear */ 11095719Sbenno mfsprg 31,0 11195719Sbenno lwz 1,PC_CURPCB(31) 11295719Sbenno addi 1,1,USPACE /* stack is top of user struct */ 11395719Sbenno1: 11495719Sbenno bla s_trap 11595719Sbenno_C_LABEL(alisize) = .-_C_LABEL(alitrap) 11695719Sbenno 11795719Sbenno/* 11895719Sbenno * Similar to the above for DSI 11995719Sbenno * Has to handle BAT spills 12095719Sbenno * and standard pagetable spills 12195719Sbenno */ 12295719Sbenno .globl _C_LABEL(dsitrap),_C_LABEL(dsisize) 12395719Sbenno_C_LABEL(dsitrap): 12495719Sbenno stmw 28,disisave(0) /* free r28-r31 */ 12595719Sbenno mfcr 29 /* save CR */ 12695719Sbenno mfxer 30 /* save XER */ 12795719Sbenno mtsprg 2,30 /* in SPRG2 */ 12895719Sbenno mfsrr1 31 /* test kernel mode */ 12995719Sbenno mtcr 31 13095719Sbenno bc 12,17,1f /* branch if PSL_PR is set */ 13195719Sbenno mfdar 31 /* get fault address */ 13295719Sbenno rlwinm 31,31,7,25,28 /* get segment * 8 */ 13395719Sbenno 13495719Sbenno /* get batu */ 13595719Sbenno addis 31,31,_C_LABEL(battable)@ha 13695719Sbenno lwz 30,_C_LABEL(battable)@l(31) 13795719Sbenno mtcr 30 13895719Sbenno bc 4,30,1f /* branch if supervisor valid is 13995719Sbenno false */ 14095719Sbenno /* get batl */ 14195719Sbenno lwz 31,_C_LABEL(battable)+4@l(31) 14295719Sbenno/* We randomly use the highest two bat registers here */ 14395719Sbenno mftb 28 14495719Sbenno andi. 28,28,1 14595719Sbenno bne 2f 14695719Sbenno mtdbatu 2,30 14795719Sbenno mtdbatl 2,31 14895719Sbenno b 3f 14995719Sbenno2: 15095719Sbenno mtdbatu 3,30 15195719Sbenno mtdbatl 3,31 15295719Sbenno3: 15395719Sbenno mfsprg 30,2 /* restore XER */ 15495719Sbenno mtxer 30 15595719Sbenno mtcr 29 /* restore CR */ 15695719Sbenno lmw 28,disisave(0) /* restore r28-r31 */ 15795719Sbenno rfi /* return to trapped code */ 15895719Sbenno1: 15995719Sbenno mflr 28 /* save LR */ 16095719Sbenno bla s_dsitrap 16195719Sbenno_C_LABEL(dsisize) = .-_C_LABEL(dsitrap) 16295719Sbenno 16395719Sbenno/* 16495719Sbenno * Dedicated MPC601 version of the above. 16595719Sbenno * Considers different BAT format and combined implementation 16695719Sbenno * (being addressed as I-BAT). 16795719Sbenno */ 16895719Sbenno .globl _C_LABEL(dsitrap601),_C_LABEL(dsi601size) 16995719Sbenno_C_LABEL(dsitrap601): 17095719Sbenno stmw 28,disisave(0) /* free r28-r31 */ 17195719Sbenno mfcr 29 /* save CR */ 17295719Sbenno mfxer 30 /* save XER */ 17395719Sbenno mtsprg 2,30 /* in SPRG2 */ 17495719Sbenno mfsrr1 31 /* test kernel mode */ 17595719Sbenno mtcr 31 17695719Sbenno bc 12,17,1f /* branch if PSL_PR is set */ 17795719Sbenno mfdar 31 /* get fault address */ 17895719Sbenno rlwinm 31,31,12,20,28 /* get "segment" battable offset */ 17995719Sbenno 18095719Sbenno /* get batl */ 18195719Sbenno addis 31,31,_C_LABEL(battable)@ha 18295719Sbenno lwz 30,_C_LABEL(battable)+4@l(31) 18395719Sbenno mtcr 30 18495719Sbenno bc 4,25,1f /* branch if Valid is is false, 18595719Sbenno presently assumes supervisor only */ 18695719Sbenno 18795719Sbenno /* get batu */ 18895719Sbenno lwz 31,_C_LABEL(battable)@l(31) 18995719Sbenno/* We randomly use the highest two bat registers here */ 19095719Sbenno mfspr 28,SPR_RTCL_R 19195719Sbenno andi. 28,28,128 19295719Sbenno bne 2f 19395719Sbenno mtibatu 2,31 19495719Sbenno mtibatl 2,30 19595719Sbenno b 3f 19695719Sbenno2: 19795719Sbenno mtibatu 3,31 19895719Sbenno mtibatl 3,30 19995719Sbenno3: 20095719Sbenno mfsprg 30,2 /* restore XER */ 20195719Sbenno mtxer 30 20295719Sbenno mtcr 29 /* restore CR */ 20395719Sbenno lmw 28,disisave(0) /* restore r28-r31 */ 20495719Sbenno rfi /* return to trapped code */ 20595719Sbenno1: 20695719Sbenno mflr 28 /* save LR */ 20795719Sbenno bla s_dsitrap 20895719Sbenno_C_LABEL(dsi601size) = .-_C_LABEL(dsitrap601) 20995719Sbenno 21095719Sbenno/* 21195719Sbenno * Similar to the above for ISI 21295719Sbenno */ 21395719Sbenno .globl _C_LABEL(isitrap),_C_LABEL(isisize) 21495719Sbenno_C_LABEL(isitrap): 21595719Sbenno stmw 28,disisave(0) /* free r28-r31 */ 21695719Sbenno mflr 28 /* save LR */ 21795719Sbenno mfcr 29 /* save CR */ 21895719Sbenno mfsrr1 31 /* test kernel mode */ 21995719Sbenno mtcr 31 22095719Sbenno bc 12,17,1f /* branch if PSL_PR is set */ 22195719Sbenno mfsrr0 31 /* get fault address */ 22295719Sbenno rlwinm 31,31,7,25,28 /* get segment * 8 */ 22395719Sbenno 22495719Sbenno /* get batu */ 22595719Sbenno addis 31,31,_C_LABEL(battable)@ha 22695719Sbenno lwz 30,_C_LABEL(battable)@l(31) 22795719Sbenno mtcr 30 22895719Sbenno bc 4,30,1f /* branch if supervisor valid is 22995719Sbenno false */ 23095719Sbenno mtibatu 3,30 23195719Sbenno 23295719Sbenno /* get batl */ 23395719Sbenno lwz 30,_C_LABEL(battable)+4@l(31) 23495719Sbenno mtibatl 3,30 23595719Sbenno 23695719Sbenno mtcr 29 /* restore CR */ 23795719Sbenno lmw 28,disisave(0) /* restore r28-r31 */ 23895719Sbenno rfi /* return to trapped code */ 23995719Sbenno1: 24095719Sbenno bla s_isitrap 24195719Sbenno_C_LABEL(isisize)= .-_C_LABEL(isitrap) 24295719Sbenno 24395719Sbenno/* 24495719Sbenno * Dedicated MPC601 version of the above. 24595719Sbenno * Considers different BAT format. 24695719Sbenno */ 24795719Sbenno .globl _C_LABEL(isitrap601),_C_LABEL(isi601size) 24895719Sbenno_C_LABEL(isitrap601): 24995719Sbenno stmw 28,disisave(0) /* free r28-r31 */ 25095719Sbenno mflr 28 /* save LR */ 25195719Sbenno mfcr 29 /* save CR */ 25295719Sbenno mfsrr1 31 /* test kernel mode */ 25395719Sbenno mtcr 31 25495719Sbenno bc 12,17,1f /* branch if PSL_PR is set */ 25595719Sbenno mfsrr0 31 /* get fault address */ 25695719Sbenno rlwinm 31,31,12,20,28 /* get "segment" battable offset */ 25795719Sbenno 25895719Sbenno /* get batl */ 25995719Sbenno addis 31,31,_C_LABEL(battable)@ha 26095719Sbenno lwz 30,_C_LABEL(battable)+4@l(31) 26195719Sbenno mtcr 30 26295719Sbenno bc 4,25,1f /* branch if Valid is is false, 26395719Sbenno presently assumes supervisor only */ 26495719Sbenno /* get batu */ 26595719Sbenno lwz 31,_C_LABEL(battable)@l(31) 26695719Sbenno 26795719Sbenno mtibatu 3,31 26895719Sbenno mtibatl 3,30 26995719Sbenno 27095719Sbenno mtcr 29 /* restore CR */ 27195719Sbenno lmw 28,disisave(0) /* restore r28-r31 */ 27295719Sbenno rfi /* return to trapped code */ 27395719Sbenno1: 27495719Sbenno bla s_isitrap 27595719Sbenno_C_LABEL(isi601size)= .-_C_LABEL(isitrap601) 27695719Sbenno 27795719Sbenno/* 27895719Sbenno * This one for the external interrupt handler. 27995719Sbenno */ 28095719Sbenno .globl _C_LABEL(extint),_C_LABEL(extsize) 28195719Sbenno_C_LABEL(extint): 28295719Sbenno mtsprg 1,1 /* save SP */ 28395719Sbenno stmw 28,tempsave(0) /* free r28-r31 */ 28495719Sbenno mflr 28 /* save LR */ 28595719Sbenno mfcr 29 /* save CR */ 28695719Sbenno mfxer 30 /* save XER */ 28795719Sbenno lis 1,intstk+INTSTK@ha /* get interrupt stack */ 28895719Sbenno addi 1,1,intstk+INTSTK@l /* this is really intr_depth! */ 28995719Sbenno lwz 31,0(1) /* were we already running on intstk? */ 29095719Sbenno addic. 31,31,1 29195719Sbenno stw 31,0(1) 29295719Sbenno beq 1f 29395719Sbenno mfsprg 1,1 /* yes, get old SP */ 29495719Sbenno1: 29595719Sbenno ba extintr 29695719Sbenno_C_LABEL(extsize) = .-_C_LABEL(extint) 29795719Sbenno 29895719Sbenno/* 29995719Sbenno * And this one for the decrementer interrupt handler. 30095719Sbenno */ 30195719Sbenno .globl _C_LABEL(decrint),_C_LABEL(decrsize) 30295719Sbenno_C_LABEL(decrint): 30395719Sbenno mtsprg 1,1 /* save SP */ 30495719Sbenno stmw 28,tempsave(0) /* free r28-r31 */ 30595719Sbenno mflr 28 /* save LR */ 30695719Sbenno mfcr 29 /* save CR */ 30795719Sbenno mfxer 30 /* save XER */ 30895719Sbenno lis 1,intstk+INTSTK@ha /* get interrupt stack */ 30995719Sbenno addi 1,1,intstk+INTSTK@l 31095719Sbenno lwz 31,0(1) /* were we already running on intstk? */ 31195719Sbenno addic. 31,31,1 31295719Sbenno stw 31,0(1) 31395719Sbenno beq 1f 31495719Sbenno mfsprg 1,1 /* yes, get old SP */ 31595719Sbenno1: 31695719Sbenno ba decrintr 31795719Sbenno_C_LABEL(decrsize) = .-_C_LABEL(decrint) 31895719Sbenno 31995719Sbenno/* 32095719Sbenno * Now the tlb software load for 603 processors: 32195719Sbenno * (Code essentially from the 603e User Manual, Chapter 5, but 32295719Sbenno * corrected a lot.) 32395719Sbenno */ 32495719Sbenno 32595719Sbenno .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize) 32695719Sbenno_C_LABEL(tlbimiss): 32795719Sbenno#ifdef PMAPDEBUG 32895719Sbenno mfspr 2,SPR_IMISS /* exception address */ 32995719Sbenno li 1,24 /* get rid of the lower */ 33095719Sbenno srw 2,2,1 /* 24 bits */ 33195719Sbenno li 1,1 /* Load 1 */ 33295719Sbenno cmpl 2,1,1 /* is it > 16MB */ 33395719Sbenno blt 99f /* nope, skip saving these SPRs */ 33495719Sbenno li 1,0xc0 /* arbitrary */ 33595719Sbenno mfspr 2,SPR_HASH1 33695719Sbenno stw 2,0(1) 33795719Sbenno mfspr 2,SPR_HASH2 33895719Sbenno stw 2,4(1) 33995719Sbenno mfspr 2,SPR_IMISS 34095719Sbenno stw 2,8(1) 34195719Sbenno mfspr 2,SPR_ICMP 34295719Sbenno stw 2,12(1) 34395719Sbenno99: 34495719Sbenno#endif /* PMAPDEBUG */ 34595719Sbenno mfspr 2,SPR_HASH1 /* get first pointer */ 34695719Sbenno li 1,8 34795719Sbenno mfctr 0 /* save counter */ 34895719Sbenno mfspr 3,SPR_ICMP /* get first compare value */ 34995719Sbenno addi 2,2,-8 /* predec pointer */ 35095719Sbenno1: 35195719Sbenno mtctr 1 /* load counter */ 35295719Sbenno2: 35395719Sbenno lwzu 1,8(2) /* get next pte */ 35495719Sbenno cmpl 0,1,3 /* see if found pte */ 35595719Sbenno bdneq 2b /* loop if not eq */ 35695719Sbenno bne 3f /* not found */ 35795719Sbenno lwz 1,4(2) /* load tlb entry lower word */ 35895719Sbenno andi. 3,1,8 /* check G-bit */ 35995719Sbenno bne 4f /* if guarded, take ISI */ 36095719Sbenno mtctr 0 /* restore counter */ 36195719Sbenno mfspr 0,SPR_IMISS /* get the miss address for the tlbli */ 36295719Sbenno mfsrr1 3 /* get the saved cr0 bits */ 36395719Sbenno mtcrf 0x80,3 /* and restore */ 36495719Sbenno ori 1,1,0x100 /* set the reference bit */ 36595719Sbenno mtspr SPR_RPA,1 /* set the pte */ 36695719Sbenno srwi 1,1,8 /* get byte 7 of pte */ 36795719Sbenno tlbli 0 /* load the itlb */ 36895719Sbenno stb 1,6(2) /* update page table */ 36995719Sbenno rfi 37095719Sbenno 37195719Sbenno3: /* not found in pteg */ 37295719Sbenno andi. 1,3,0x40 /* have we already done second hash? */ 37395719Sbenno bne 5f 37495719Sbenno mfspr 2,SPR_HASH2 /* get the second pointer */ 37595719Sbenno ori 3,3,0x40 /* change the compare value */ 37695719Sbenno li 1,8 37795719Sbenno addi 2,2,-8 /* predec pointer */ 37895719Sbenno b 1b 37995719Sbenno4: /* guarded */ 38095719Sbenno mfsrr1 3 38195719Sbenno andi. 2,3,0xffff /* clean upper srr1 */ 38295719Sbenno oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ 38395719Sbenno b 6f 38495719Sbenno5: /* not found anywhere */ 38595719Sbenno mfsrr1 3 38695719Sbenno andi. 2,3,0xffff /* clean upper srr1 */ 38795719Sbenno oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ 38895719Sbenno6: 38995719Sbenno mtctr 0 /* restore counter */ 39095719Sbenno mtsrr1 2 39195719Sbenno mfmsr 0 39295719Sbenno xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 39395719Sbenno mtcrf 0x80,3 /* restore cr0 */ 39495719Sbenno mtmsr 0 /* now with native gprs */ 39595719Sbenno isync 39695719Sbenno ba EXC_ISI 39795719Sbenno_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss) 39895719Sbenno 39995719Sbenno .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize) 40095719Sbenno_C_LABEL(tlbdlmiss): 40195719Sbenno mfspr 2,SPR_HASH1 /* get first pointer */ 40295719Sbenno li 1,8 40395719Sbenno mfctr 0 /* save counter */ 40495719Sbenno mfspr 3,SPR_DCMP /* get first compare value */ 40595719Sbenno addi 2,2,-8 /* predec pointer */ 40695719Sbenno1: 40795719Sbenno mtctr 1 /* load counter */ 40895719Sbenno2: 40995719Sbenno lwzu 1,8(2) /* get next pte */ 41095719Sbenno cmpl 0,1,3 /* see if found pte */ 41195719Sbenno bdneq 2b /* loop if not eq */ 41295719Sbenno bne 3f /* not found */ 41395719Sbenno lwz 1,4(2) /* load tlb entry lower word */ 41495719Sbenno mtctr 0 /* restore counter */ 41595719Sbenno mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ 41695719Sbenno mfsrr1 3 /* get the saved cr0 bits */ 41795719Sbenno mtcrf 0x80,3 /* and restore */ 41895719Sbenno ori 1,1,0x100 /* set the reference bit */ 41995719Sbenno mtspr SPR_RPA,1 /* set the pte */ 42095719Sbenno srwi 1,1,8 /* get byte 7 of pte */ 42195719Sbenno tlbld 0 /* load the dtlb */ 42295719Sbenno stb 1,6(2) /* update page table */ 42395719Sbenno rfi 42495719Sbenno 42595719Sbenno3: /* not found in pteg */ 42695719Sbenno andi. 1,3,0x40 /* have we already done second hash? */ 42795719Sbenno bne 5f 42895719Sbenno mfspr 2,SPR_HASH2 /* get the second pointer */ 42995719Sbenno ori 3,3,0x40 /* change the compare value */ 43095719Sbenno li 1,8 43195719Sbenno addi 2,2,-8 /* predec pointer */ 43295719Sbenno b 1b 43395719Sbenno5: /* not found anywhere */ 43495719Sbenno mfsrr1 3 43595719Sbenno lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ 43695719Sbenno mtctr 0 /* restore counter */ 43795719Sbenno andi. 2,3,0xffff /* clean upper srr1 */ 43895719Sbenno mtsrr1 2 43995719Sbenno mtdsisr 1 /* load the dsisr */ 44095719Sbenno mfspr 1,SPR_DMISS /* get the miss address */ 44195719Sbenno mtdar 1 /* put in dar */ 44295719Sbenno mfmsr 0 44395719Sbenno xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 44495719Sbenno mtcrf 0x80,3 /* restore cr0 */ 44595719Sbenno mtmsr 0 /* now with native gprs */ 44695719Sbenno isync 44795719Sbenno ba EXC_DSI 44895719Sbenno_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss) 44995719Sbenno 45095719Sbenno .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize) 45195719Sbenno_C_LABEL(tlbdsmiss): 45295719Sbenno mfspr 2,SPR_HASH1 /* get first pointer */ 45395719Sbenno li 1,8 45495719Sbenno mfctr 0 /* save counter */ 45595719Sbenno mfspr 3,SPR_DCMP /* get first compare value */ 45695719Sbenno addi 2,2,-8 /* predec pointer */ 45795719Sbenno1: 45895719Sbenno mtctr 1 /* load counter */ 45995719Sbenno2: 46095719Sbenno lwzu 1,8(2) /* get next pte */ 46195719Sbenno cmpl 0,1,3 /* see if found pte */ 46295719Sbenno bdneq 2b /* loop if not eq */ 46395719Sbenno bne 3f /* not found */ 46495719Sbenno lwz 1,4(2) /* load tlb entry lower word */ 46595719Sbenno andi. 3,1,0x80 /* check the C-bit */ 46695719Sbenno beq 4f 46795719Sbenno5: 46895719Sbenno mtctr 0 /* restore counter */ 46995719Sbenno mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ 47095719Sbenno mfsrr1 3 /* get the saved cr0 bits */ 47195719Sbenno mtcrf 0x80,3 /* and restore */ 47295719Sbenno mtspr SPR_RPA,1 /* set the pte */ 47395719Sbenno tlbld 0 /* load the dtlb */ 47495719Sbenno rfi 47595719Sbenno 47695719Sbenno3: /* not found in pteg */ 47795719Sbenno andi. 1,3,0x40 /* have we already done second hash? */ 47895719Sbenno bne 5f 47995719Sbenno mfspr 2,SPR_HASH2 /* get the second pointer */ 48095719Sbenno ori 3,3,0x40 /* change the compare value */ 48195719Sbenno li 1,8 48295719Sbenno addi 2,2,-8 /* predec pointer */ 48395719Sbenno b 1b 48495719Sbenno4: /* found, but C-bit = 0 */ 48595719Sbenno rlwinm. 3,1,30,0,1 /* test PP */ 48695719Sbenno bge- 7f 48795719Sbenno andi. 3,1,1 48895719Sbenno beq+ 8f 48995719Sbenno9: /* found, but protection violation (PP==00)*/ 49095719Sbenno mfsrr1 3 49195719Sbenno lis 1,0xa000000@h /* indicate protection violation 49295719Sbenno on store */ 49395719Sbenno b 1f 49495719Sbenno7: /* found, PP=1x */ 49595719Sbenno mfspr 3,SPR_DMISS /* get the miss address */ 49695719Sbenno mfsrin 1,3 /* get the segment register */ 49795719Sbenno mfsrr1 3 49895719Sbenno rlwinm 3,3,18,31,31 /* get PR-bit */ 49995719Sbenno rlwnm. 2,2,3,1,1 /* get the key */ 50095719Sbenno bne- 9b /* protection violation */ 50195719Sbenno8: /* found, set reference/change bits */ 50295719Sbenno lwz 1,4(2) /* reload tlb entry */ 50395719Sbenno ori 1,1,0x180 50495719Sbenno sth 1,6(2) 50595719Sbenno b 5b 50695719Sbenno5: /* not found anywhere */ 50795719Sbenno mfsrr1 3 50895719Sbenno lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ 50995719Sbenno /* dsisr<6> to flag store */ 51095719Sbenno1: 51195719Sbenno mtctr 0 /* restore counter */ 51295719Sbenno andi. 2,3,0xffff /* clean upper srr1 */ 51395719Sbenno mtsrr1 2 51495719Sbenno mtdsisr 1 /* load the dsisr */ 51595719Sbenno mfspr 1,SPR_DMISS /* get the miss address */ 51695719Sbenno mtdar 1 /* put in dar */ 51795719Sbenno mfmsr 0 51895719Sbenno xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 51995719Sbenno mtcrf 0x80,3 /* restore cr0 */ 52095719Sbenno mtmsr 0 /* now with native gprs */ 52195719Sbenno isync 52295719Sbenno ba EXC_DSI 52395719Sbenno_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss) 52495719Sbenno 52595719Sbenno#if defined(DDB) || defined(KGDB) 52695719Sbenno#define ddbsave 0xde0 /* primary save area for DDB */ 52795719Sbenno/* 52895719Sbenno * In case of DDB we want a separate trap catcher for it 52995719Sbenno */ 53095719Sbenno .local ddbstk 53195719Sbenno .comm ddbstk,INTSTK,8 /* ddb stack */ 53295719Sbenno 53395719Sbenno .globl _C_LABEL(ddblow),_C_LABEL(ddbsize) 53495719Sbenno_C_LABEL(ddblow): 53595719Sbenno mtsprg 1,1 /* save SP */ 53695719Sbenno stmw 28,ddbsave(0) /* free r28-r31 */ 53795719Sbenno mflr 28 /* save LR */ 53895719Sbenno mfcr 29 /* save CR */ 53995719Sbenno lis 1,ddbstk+INTSTK@ha /* get new SP */ 54095719Sbenno addi 1,1,ddbstk+INTSTK@l 54195719Sbenno bla ddbtrap 54295719Sbenno_C_LABEL(ddbsize) = .-_C_LABEL(ddblow) 54395719Sbenno#endif /* DDB | KGDB */ 54495719Sbenno 54595719Sbenno#ifdef IPKDB 54695719Sbenno#define ipkdbsave 0xde0 /* primary save area for IPKDB */ 54795719Sbenno/* 54895719Sbenno * In case of IPKDB we want a separate trap catcher for it 54995719Sbenno */ 55095719Sbenno 55195719Sbenno .local ipkdbstk 55295719Sbenno .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ 55395719Sbenno 55495719Sbenno .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize) 55595719Sbenno_C_LABEL(ipkdblow): 55695719Sbenno mtsprg 1,1 /* save SP */ 55795719Sbenno stmw 28,ipkdbsave(0) /* free r28-r31 */ 55895719Sbenno mflr 28 /* save LR */ 55995719Sbenno mfcr 29 /* save CR */ 56095719Sbenno lis 1,ipkdbstk+INTSTK@ha /* get new SP */ 56195719Sbenno addi 1,1,ipkdbstk+INTSTK@l 56295719Sbenno bla ipkdbtrap 56395719Sbenno_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow) 56495719Sbenno#endif /* IPKDB */ 56595719Sbenno 56695719Sbenno/* 56795719Sbenno * FRAME_SETUP assumes: 56895719Sbenno * SPRG1 SP (1) 56995719Sbenno * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) 57095719Sbenno * 28 LR 57195719Sbenno * 29 CR 57295719Sbenno * 1 kernel stack 57395719Sbenno * LR trap type 57495719Sbenno * SRR0/1 as at start of trap 57595719Sbenno */ 57695719Sbenno#define FRAME_SETUP(savearea) \ 57795719Sbenno/* Have to enable translation to allow access of kernel stack: */ \ 57895719Sbenno mfsrr0 30; \ 57995719Sbenno mfsrr1 31; \ 58095719Sbenno stmw 30,savearea+24(0); \ 58195719Sbenno mfmsr 30; \ 58295719Sbenno ori 30,30,(PSL_DR|PSL_IR); \ 58395719Sbenno mtmsr 30; \ 58495719Sbenno isync; \ 58595719Sbenno mfsprg 31,1; \ 58695719Sbenno stwu 31,-FRAMELEN(1); \ 58795719Sbenno stw 0,FRAME_0+8(1); \ 58895719Sbenno stw 31,FRAME_1+8(1); \ 58995719Sbenno stw 28,FRAME_LR+8(1); \ 59095719Sbenno stw 29,FRAME_CR+8(1); \ 59195719Sbenno lmw 28,savearea(0); \ 59295719Sbenno stmw 2,FRAME_2+8(1); \ 59395719Sbenno lmw 28,savearea+16(0); \ 59495719Sbenno mfxer 3; \ 59595719Sbenno mfctr 4; \ 59695719Sbenno mflr 5; \ 59795719Sbenno andi. 5,5,0xff00; \ 59895719Sbenno stw 3,FRAME_XER+8(1); \ 59995719Sbenno stw 4,FRAME_CTR+8(1); \ 60095719Sbenno stw 5,FRAME_EXC+8(1); \ 60195719Sbenno stw 28,FRAME_DAR+8(1); \ 60295719Sbenno stw 29,FRAME_DSISR+8(1); \ 60395719Sbenno stw 30,FRAME_SRR0+8(1); \ 60495719Sbenno stw 31,FRAME_SRR1+8(1) 60595719Sbenno 60695719Sbenno#define FRAME_LEAVE(savearea) \ 60795719Sbenno/* Now restore regs: */ \ 60895719Sbenno lwz 2,FRAME_SRR0+8(1); \ 60995719Sbenno lwz 3,FRAME_SRR1+8(1); \ 61095719Sbenno lwz 4,FRAME_CTR+8(1); \ 61195719Sbenno lwz 5,FRAME_XER+8(1); \ 61295719Sbenno lwz 6,FRAME_LR+8(1); \ 61395719Sbenno lwz 7,FRAME_CR+8(1); \ 61495719Sbenno stw 2,savearea(0); \ 61595719Sbenno stw 3,savearea+4(0); \ 61695719Sbenno mtctr 4; \ 61795719Sbenno mtxer 5; \ 61895719Sbenno mtlr 6; \ 61995719Sbenno mtsprg 1,7; /* save cr */ \ 62095719Sbenno lmw 2,FRAME_2+8(1); \ 62195719Sbenno lwz 0,FRAME_0+8(1); \ 62295719Sbenno lwz 1,FRAME_1+8(1); \ 62395719Sbenno mtsprg 2,2; /* save r2 & r3 */ \ 62495719Sbenno mtsprg 3,3; \ 62595719Sbenno/* Disable translation, machine check and recoverability: */ \ 62695719Sbenno mfmsr 2; \ 62795719Sbenno andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ 62895719Sbenno mtmsr 2; \ 62995719Sbenno isync; \ 63095719Sbenno/* Decide whether we return to user mode: */ \ 63195719Sbenno lwz 3,savearea+4(0); \ 63295719Sbenno mtcr 3; \ 63395719Sbenno bc 4,17,1f; /* branch if PSL_PR is false */ \ 63495719Sbenno/* Restore user & kernel access SR: */ \ 63595719Sbenno mfsprg 2,0; \ 63695719Sbenno lwz 2,PC_CURPMAP(2); \ 63795719Sbenno lwz 3,PM_SR+0(2); \ 63895719Sbenno mtsr 0,3; /* restore SR0 */ \ 63995719Sbenno lwz 3,PM_SR+4(2); \ 64095719Sbenno mtsr 1,3; /* restore SR1 */ \ 64195719Sbenno lwz 3,PM_SR+8(2); \ 64295719Sbenno mtsr 2,3; /* restore SR2 */ \ 64395719Sbenno lwz 3,PM_SR+12(2); \ 64495719Sbenno mtsr 3,3; /* restore SR3 */ \ 64595719Sbenno lwz 3,PM_SR+16(2); \ 64695719Sbenno mtsr 4,3; /* restore SR4 */ \ 64795719Sbenno lwz 3,PM_SR+20(2); \ 64895719Sbenno mtsr 5,3; /* restore SR5 */ \ 64995719Sbenno lwz 3,PM_SR+24(2); \ 65095719Sbenno mtsr 6,3; /* restore SR6 */ \ 65195719Sbenno lwz 3,PM_SR+28(2); \ 65295719Sbenno mtsr 7,3; /* restore SR7 */ \ 65395719Sbenno lwz 3,PM_USRSR(2); \ 65495719Sbenno mtsr USER_SR,3; \ 65595719Sbenno lwz 3,PM_KERNELSR(2); \ 65695719Sbenno mtsr KERNEL_SR,3; \ 65795719Sbenno1: mfsprg 2,1; /* restore cr */ \ 65895719Sbenno mtcr 2; \ 65995719Sbenno lwz 2,savearea(0); \ 66095719Sbenno lwz 3,savearea+4(0); \ 66195719Sbenno mtsrr0 2; \ 66295719Sbenno mtsrr1 3; \ 66395719Sbenno mfsprg 2,2; /* restore r2 & r3 */ \ 66495719Sbenno mfsprg 3,3 66595719Sbenno 66695719Sbenno/* 66795719Sbenno * Preamble code for DSI/ISI traps 66895719Sbenno */ 66995719Sbennodisitrap: 67095719Sbenno lmw 30,disisave(0) 67195719Sbenno stmw 30,tempsave(0) 67295719Sbenno lmw 30,disisave+8(0) 67395719Sbenno stmw 30,tempsave+8(0) 67495719Sbenno mfdar 30 67595719Sbenno mfdsisr 31 67695719Sbenno stmw 30,tempsave+16(0) 67795719Sbennorealtrap: 67895719Sbenno/* Test whether we already had PR set */ 67995719Sbenno mfsrr1 1 68095719Sbenno mtcr 1 68195719Sbenno mfsprg 1,1 /* restore SP (might have been 68295719Sbenno overwritten) */ 68395719Sbenno bc 4,17,s_trap /* branch if PSL_PR is false */ 68495719Sbenno mfsprg 31,0 68595719Sbenno lwz 1,PC_CURPCB(31) 68695719Sbenno addi 1,1,USPACE /* stack is top of user struct */ 68795719Sbenno 68895719Sbenno/* 68995719Sbenno * Now the common trap catching code. 69095719Sbenno */ 69195719Sbennos_trap: 69295719Sbenno/* First have to enable KERNEL mapping */ 69395719Sbenno lis 31,KERNEL_SEGMENT@h 69495719Sbenno ori 31,31,KERNEL_SEGMENT@l 69595719Sbenno mtsr KERNEL_SR,31 69695719Sbenno/* Obliterate SRs so BAT spills work correctly */ 69795719Sbenno lis 31,EMPTY_SEGMENT@h 69895719Sbenno ori 31,31,EMPTY_SEGMENT@l 69995719Sbenno mtsr 0,31 70095719Sbenno mtsr 1,31 70195719Sbenno mtsr 2,31 70295719Sbenno mtsr 3,31 70395719Sbenno mtsr 4,31 70495719Sbenno mtsr 5,31 70595719Sbenno mtsr 6,31 70695719Sbenno mtsr 7,31 70795719Sbenno FRAME_SETUP(tempsave) 70895719Sbenno/* Now we can recover interrupts again: */ 70995719Sbenno mfmsr 7 71095719Sbenno ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l 71195719Sbenno mtmsr 7 71295719Sbenno isync 71395719Sbenno/* Call C trap code: */ 71495719Sbennotrapagain: 71595719Sbenno addi 3,1,8 71695719Sbenno bl _C_LABEL(trap) 71795719Sbenno .globl _C_LABEL(trapexit) 71895719Sbenno_C_LABEL(trapexit): 71995719Sbenno/* Disable interrupts: */ 72095719Sbenno mfmsr 3 72195719Sbenno andi. 3,3,~PSL_EE@l 72295719Sbenno mtmsr 3 72395719Sbenno/* Test AST pending: */ 72495719Sbenno lwz 5,FRAME_SRR1+8(1) 72595719Sbenno mtcr 5 72695719Sbenno bc 4,17,1f /* branch if PSL_PR is false */ 72795719Sbenno lis 3,_C_LABEL(astpending)@ha 72895719Sbenno lwz 4,_C_LABEL(astpending)@l(3) 72995719Sbenno andi. 4,4,1 73095719Sbenno beq 1f 73195719Sbenno li 6,EXC_AST 73295719Sbenno stw 6,FRAME_EXC+8(1) 73395719Sbenno b trapagain 73495719Sbenno1: 73595719Sbenno FRAME_LEAVE(tempsave) 73695719Sbenno rfi 73795719Sbenno 73895719Sbenno/* 73995719Sbenno * DSI second stage fault handler 74095719Sbenno */ 74195719Sbennos_dsitrap: 74295719Sbenno mfdsisr 31 /* test whether this may be a 74395719Sbenno spill fault */ 74495719Sbenno mtcr 31 74595719Sbenno mtsprg 1,1 /* save SP */ 74695719Sbenno bc 4,1,disitrap /* branch if table miss is false */ 74795719Sbenno lis 1,spillstk+SPILLSTK@ha 74895719Sbenno addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 74995719Sbenno stwu 1,-SPFRAMELEN(1) 75095719Sbenno stw 0,SPFRAME_R0(1) /* save non-volatile registers */ 75195719Sbenno stw 3,SPFRAME_R3(1) 75295719Sbenno stw 4,SPFRAME_R4(1) 75395719Sbenno stw 5,SPFRAME_R5(1) 75495719Sbenno stw 6,SPFRAME_R6(1) 75595719Sbenno stw 7,SPFRAME_R7(1) 75695719Sbenno stw 8,SPFRAME_R8(1) 75795719Sbenno stw 9,SPFRAME_R9(1) 75895719Sbenno stw 10,SPFRAME_R10(1) 75995719Sbenno stw 11,SPFRAME_R11(1) 76095719Sbenno stw 12,SPFRAME_R12(1) 76195719Sbenno mflr 30 /* save trap type */ 76295719Sbenno mfctr 31 /* & CTR */ 76395719Sbenno mfdar 3 76495719Sbennos_pte_spill: 76595719Sbenno bl _C_LABEL(pmap_pte_spill) /* try a spill */ 76695719Sbenno or. 3,3,3 76795719Sbenno mtctr 31 /* restore CTR */ 76895719Sbenno mtlr 30 /* and trap type */ 76995719Sbenno mfsprg 31,2 /* get saved XER */ 77095719Sbenno mtxer 31 /* restore XER */ 77195719Sbenno lwz 12,SPFRAME_R12(1) /* restore non-volatile registers */ 77295719Sbenno lwz 11,SPFRAME_R11(1) 77395719Sbenno lwz 10,SPFRAME_R10(1) 77495719Sbenno lwz 9,SPFRAME_R9(1) 77595719Sbenno lwz 8,SPFRAME_R8(1) 77695719Sbenno lwz 7,SPFRAME_R7(1) 77795719Sbenno lwz 6,SPFRAME_R6(1) 77895719Sbenno lwz 5,SPFRAME_R5(1) 77995719Sbenno lwz 4,SPFRAME_R4(1) 78095719Sbenno lwz 3,SPFRAME_R3(1) 78195719Sbenno lwz 0,SPFRAME_R0(1) 78295719Sbenno beq disitrap 78395719Sbenno mfsprg 1,1 /* restore SP */ 78495719Sbenno mtcr 29 /* restore CR */ 78595719Sbenno mtlr 28 /* restore LR */ 78695719Sbenno lmw 28,disisave(0) /* restore r28-r31 */ 78795719Sbenno rfi /* return to trapped code */ 78895719Sbenno 78995719Sbenno/* 79095719Sbenno * ISI second stage fault handler 79195719Sbenno */ 79295719Sbennos_isitrap: 79395719Sbenno mfsrr1 31 /* test whether this may be a 79495719Sbenno spill fault */ 79595719Sbenno mtcr 31 79695719Sbenno mtsprg 1,1 /* save SP */ 79795719Sbenno bc 4,1,disitrap /* branch if table miss is false */ 79895719Sbenno lis 1,spillstk+SPILLSTK@ha 79995719Sbenno addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 80095719Sbenno stwu 1,-SPFRAMELEN(1) 80195719Sbenno stw 0,SPFRAME_R0(1) /* save non-volatile registers */ 80295719Sbenno stw 3,SPFRAME_R3(1) 80395719Sbenno stw 4,SPFRAME_R4(1) 80495719Sbenno stw 5,SPFRAME_R5(1) 80595719Sbenno stw 6,SPFRAME_R6(1) 80695719Sbenno stw 7,SPFRAME_R7(1) 80795719Sbenno stw 8,SPFRAME_R8(1) 80895719Sbenno stw 9,SPFRAME_R9(1) 80995719Sbenno stw 10,SPFRAME_R10(1) 81095719Sbenno stw 11,SPFRAME_R11(1) 81195719Sbenno stw 12,SPFRAME_R12(1) 81295719Sbenno mfxer 30 /* save XER */ 81395719Sbenno mtsprg 2,30 81495719Sbenno mflr 30 /* save trap type */ 81595719Sbenno mfctr 31 /* & ctr */ 81695719Sbenno mfsrr0 3 81795719Sbenno b s_pte_spill /* above */ 81895719Sbenno 81995719Sbenno/* 82095719Sbenno * External interrupt second level handler 82195719Sbenno */ 82295719Sbenno#define INTRENTER \ 82395719Sbenno/* Save non-volatile registers: */ \ 82495719Sbenno stwu 1,-IFRAMELEN(1); /* temporarily */ \ 82595719Sbenno stw 0,IFRAME_R0(1); \ 82695719Sbenno mfsprg 0,1; /* get original SP */ \ 82795719Sbenno stw 0,IFRAME_R1(1); /* and store it */ \ 82895719Sbenno stw 3,IFRAME_R3(1); \ 82995719Sbenno stw 4,IFRAME_R4(1); \ 83095719Sbenno stw 5,IFRAME_R5(1); \ 83195719Sbenno stw 6,IFRAME_R6(1); \ 83295719Sbenno stw 7,IFRAME_R7(1); \ 83395719Sbenno stw 8,IFRAME_R8(1); \ 83495719Sbenno stw 9,IFRAME_R9(1); \ 83595719Sbenno stw 10,IFRAME_R10(1); \ 83695719Sbenno stw 11,IFRAME_R11(1); \ 83795719Sbenno stw 12,IFRAME_R12(1); \ 83895719Sbenno stw 28,IFRAME_LR(1); /* saved LR */ \ 83995719Sbenno stw 29,IFRAME_CR(1); /* saved CR */ \ 84095719Sbenno stw 30,IFRAME_XER(1); /* saved XER */ \ 84195719Sbenno lmw 28,tempsave(0); /* restore r28-r31 */ \ 84295719Sbenno mfctr 6; \ 84395719Sbenno lis 5,_C_LABEL(intr_depth)@ha; \ 84495719Sbenno lwz 5,_C_LABEL(intr_depth)@l(5); \ 84595719Sbenno mfsrr0 4; \ 84695719Sbenno mfsrr1 3; \ 84795719Sbenno stw 6,IFRAME_CTR(1); \ 84895719Sbenno stw 5,IFRAME_INTR_DEPTH(1); \ 84995719Sbenno stw 4,IFRAME_SRR0(1); \ 85095719Sbenno stw 3,IFRAME_SRR1(1); \ 85195719Sbenno mtcr 3; \ 85295719Sbenno bc 4,17,99f; /* branch if PSL_PR is false */ \ 85395719Sbenno lis 3,EMPTY_SEGMENT@h; \ 85495719Sbenno ori 3,3,EMPTY_SEGMENT@l; \ 85595719Sbenno mtsr 0,3; /* reset SRs so BAT spills work */ \ 85695719Sbenno mtsr 1,3; \ 85795719Sbenno mtsr 2,3; \ 85895719Sbenno mtsr 3,3; \ 85995719Sbenno mtsr 4,3; \ 86095719Sbenno mtsr 5,3; \ 86195719Sbenno mtsr 6,3; \ 86295719Sbenno mtsr 7,3; \ 86395719Sbenno/* interrupts are recoverable here, and enable translation */ \ 86495719Sbenno lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ 86595719Sbenno ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ 86695719Sbenno mtsr KERNEL_SR,3; \ 86795719Sbenno99: mfmsr 5; \ 86895719Sbenno ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ 86995719Sbenno mtmsr 5; \ 87095719Sbenno isync 87195719Sbenno 87295719Sbenno .globl _C_LABEL(extint_call) 87395719Sbennoextintr: 87495719Sbenno INTRENTER 87595719Sbenno_C_LABEL(extint_call): 87695719Sbenno bl _C_LABEL(extint_call) /* to be filled in later */ 87795719Sbenno 87895719Sbennointr_exit: 87995719Sbenno/* Disable interrupts (should already be disabled) and MMU here: */ 88095719Sbenno mfmsr 3 88195719Sbenno andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l 88295719Sbenno mtmsr 3 88395719Sbenno isync 88495719Sbenno/* restore possibly overwritten registers: */ 88595719Sbenno lwz 12,IFRAME_R12(1) 88695719Sbenno lwz 11,IFRAME_R11(1) 88795719Sbenno lwz 10,IFRAME_R10(1) 88895719Sbenno lwz 9,IFRAME_R9(1) 88995719Sbenno lwz 8,IFRAME_R8(1) 89095719Sbenno lwz 7,IFRAME_R7(1) 89195719Sbenno lwz 6,IFRAME_SRR1(1) 89295719Sbenno lwz 5,IFRAME_SRR0(1) 89395719Sbenno lwz 4,IFRAME_CTR(1) 89495719Sbenno lwz 3,IFRAME_XER(1) 89595719Sbenno mtsrr1 6 89695719Sbenno mtsrr0 5 89795719Sbenno mtctr 4 89895719Sbenno mtxer 3 89995719Sbenno/* Returning to user mode? */ 90095719Sbenno mtcr 6 /* saved SRR1 */ 90195719Sbenno bc 4,17,1f /* branch if PSL_PR is false */ 90295719Sbenno mfsprg 31,0 90395719Sbenno lwz 3,PC_CURPMAP(31) 90495719Sbenno lwz 4,PM_SR+0(3) 90595719Sbenno mtsr 0,4 /* Restore SR0 */ 90695719Sbenno lwz 4,PM_SR+4(3) 90795719Sbenno mtsr 1,4 /* Restore SR1 */ 90895719Sbenno lwz 4,PM_SR+8(3) 90995719Sbenno mtsr 2,4 /* Restore SR2 */ 91095719Sbenno lwz 4,PM_SR+12(3) 91195719Sbenno mtsr 3,4 /* Restore SR3 */ 91295719Sbenno lwz 4,PM_SR+16(3) 91395719Sbenno mtsr 4,4 /* Restore SR4 */ 91495719Sbenno lwz 4,PM_SR+20(3) 91595719Sbenno mtsr 5,4 /* Restore SR5 */ 91695719Sbenno lwz 4,PM_SR+24(3) 91795719Sbenno mtsr 6,4 /* Restore SR6 */ 91895719Sbenno lwz 4,PM_SR+28(3) 91995719Sbenno mtsr 7,4 /* Restore SR7 */ 92095719Sbenno lwz 3,PM_KERNELSR(3) 92195719Sbenno mtsr KERNEL_SR,3 /* Restore kernel SR */ 92295719Sbenno lis 3,_C_LABEL(astpending)@ha /* Test AST pending */ 92395719Sbenno lwz 4,_C_LABEL(astpending)@l(3) 92495719Sbenno andi. 4,4,1 92595719Sbenno beq 1f 92695719Sbenno/* Setup for entry to realtrap: */ 92795719Sbenno lwz 3,IFRAME_R1(1) /* get saved SP */ 92895719Sbenno mtsprg 1,3 92995719Sbenno li 6,EXC_AST 93095719Sbenno stmw 28,tempsave(0) /* establish tempsave again */ 93195719Sbenno mtlr 6 93295719Sbenno lwz 28,IFRAME_LR(1) /* saved LR */ 93395719Sbenno lwz 29,IFRAME_CR(1) /* saved CR */ 93495719Sbenno lwz 6,IFRAME_R6(1) 93595719Sbenno lwz 5,IFRAME_R5(1) 93695719Sbenno lwz 4,IFRAME_R4(1) 93795719Sbenno lwz 3,IFRAME_R3(1) 93895719Sbenno lwz 0,IFRAME_R0(1) 93995719Sbenno lis 30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ 94095719Sbenno lwz 31,_C_LABEL(intr_depth)@l(30) 94195719Sbenno addi 31,31,-1 94295719Sbenno stw 31,_C_LABEL(intr_depth)@l(30) 94395719Sbenno b realtrap 94495719Sbenno1: 94595719Sbenno/* Here is the normal exit of extintr: */ 94695719Sbenno lwz 5,IFRAME_CR(1) 94795719Sbenno lwz 6,IFRAME_LR(1) 94895719Sbenno mtcr 5 94995719Sbenno mtlr 6 95095719Sbenno lwz 6,IFRAME_R6(1) 95195719Sbenno lwz 5,IFRAME_R5(1) 95295719Sbenno lis 3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ 95395719Sbenno lwz 4,_C_LABEL(intr_depth)@l(3) 95495719Sbenno addi 4,4,-1 95595719Sbenno stw 4,_C_LABEL(intr_depth)@l(3) 95695719Sbenno lwz 4,IFRAME_R4(1) 95795719Sbenno lwz 3,IFRAME_R3(1) 95895719Sbenno lwz 0,IFRAME_R0(1) 95995719Sbenno lwz 1,IFRAME_R1(1) 96095719Sbenno rfi 96195719Sbenno 96295719Sbenno/* 96395719Sbenno * Decrementer interrupt second level handler 96495719Sbenno */ 96595719Sbennodecrintr: 96695719Sbenno INTRENTER 96795719Sbenno addi 3,1,8 /* intr frame -> clock frame */ 96895719Sbenno bl _C_LABEL(decr_intr) 96995719Sbenno b intr_exit 97095719Sbenno 97195719Sbenno#if defined(DDB) 97295719Sbenno/* 97395719Sbenno * Deliberate entry to ddbtrap 97495719Sbenno */ 97595719Sbenno .globl _C_LABEL(ddb_trap) 97695719Sbenno_C_LABEL(ddb_trap): 97795719Sbenno mtsprg 1,1 97895719Sbenno mfmsr 3 97995719Sbenno mtsrr1 3 98095719Sbenno andi. 3,3,~(PSL_EE|PSL_ME)@l 98195719Sbenno mtmsr 3 /* disable interrupts */ 98295719Sbenno isync 98395719Sbenno stmw 28,ddbsave(0) 98495719Sbenno mflr 28 98595719Sbenno li 29,EXC_BPT 98695719Sbenno mtlr 29 98795719Sbenno mfcr 29 98895719Sbenno mtsrr0 28 98995719Sbenno#endif /* DDB */ 99095719Sbenno 99195719Sbenno#if defined(DDB) || defined(KGDB) 99295719Sbenno/* 99395719Sbenno * Now the ddb trap catching code. 99495719Sbenno */ 99595719Sbennoddbtrap: 99695719Sbenno FRAME_SETUP(ddbsave) 99795719Sbenno/* Call C trap code: */ 99895719Sbenno addi 3,1,8 99995719Sbenno bl _C_LABEL(ddb_trap_glue) 100095719Sbenno or. 3,3,3 100195719Sbenno bne ddbleave 100295719Sbenno/* This wasn't for DDB, so switch to real trap: */ 100395719Sbenno lwz 3,FRAME_EXC+8(1) /* save exception */ 100495719Sbenno stw 3,ddbsave+8(0) 100595719Sbenno FRAME_LEAVE(ddbsave) 100695719Sbenno mtsprg 1,1 /* prepare for entrance to realtrap */ 100795719Sbenno stmw 28,tempsave(0) 100895719Sbenno mflr 28 100995719Sbenno mfcr 29 101095719Sbenno lwz 31,ddbsave+8(0) 101195719Sbenno mtlr 31 101295719Sbenno b realtrap 101395719Sbennoddbleave: 101495719Sbenno FRAME_LEAVE(ddbsave) 101595719Sbenno rfi 101695719Sbenno#endif /* DDB || KGDB */ 101795719Sbenno 101895719Sbenno#ifdef IPKDB 101995719Sbenno/* 102095719Sbenno * Deliberate entry to ipkdbtrap 102195719Sbenno */ 102295719Sbenno .globl _C_LABEL(ipkdb_trap) 102395719Sbenno_C_LABEL(ipkdb_trap): 102495719Sbenno mtsprg 1,1 102595719Sbenno mfmsr 3 102695719Sbenno mtsrr1 3 102795719Sbenno andi. 3,3,~(PSL_EE|PSL_ME)@l 102895719Sbenno mtmsr 3 /* disable interrupts */ 102995719Sbenno isync 103095719Sbenno stmw 28,ipkdbsave(0) 103195719Sbenno mflr 28 103295719Sbenno li 29,EXC_BPT 103395719Sbenno mtlr 29 103495719Sbenno mfcr 29 103595719Sbenno mtsrr0 28 103695719Sbenno 103795719Sbenno/* 103895719Sbenno * Now the ipkdb trap catching code. 103995719Sbenno */ 104095719Sbennoipkdbtrap: 104195719Sbenno FRAME_SETUP(ipkdbsave) 104295719Sbenno/* Call C trap code: */ 104395719Sbenno addi 3,1,8 104495719Sbenno bl _C_LABEL(ipkdb_trap_glue) 104595719Sbenno or. 3,3,3 104695719Sbenno bne ipkdbleave 104795719Sbenno/* This wasn't for IPKDB, so switch to real trap: */ 104895719Sbenno lwz 3,FRAME_EXC+8(1) /* save exception */ 104995719Sbenno stw 3,ipkdbsave+8(0) 105095719Sbenno FRAME_LEAVE(ipkdbsave) 105195719Sbenno mtsprg 1,1 /* prepare for entrance to realtrap */ 105295719Sbenno stmw 28,tempsave(0) 105395719Sbenno mflr 28 105495719Sbenno mfcr 29 105595719Sbenno lwz 31,ipkdbsave+8(0) 105695719Sbenno mtlr 31 105795719Sbenno b realtrap 105895719Sbennoipkdbleave: 105995719Sbenno FRAME_LEAVE(ipkdbsave) 106095719Sbenno rfi 106195719Sbenno 106295719Sbennoipkdbfault: 106395719Sbenno ba _ipkdbfault 106495719Sbenno_ipkdbfault: 106595719Sbenno mfsrr0 3 106695719Sbenno addi 3,3,4 106795719Sbenno mtsrr0 3 106895719Sbenno li 3,-1 106995719Sbenno rfi 107095719Sbenno 107195719Sbenno/* 107295719Sbenno * int ipkdbfbyte(unsigned char *p) 107395719Sbenno */ 107495719Sbenno .globl _C_LABEL(ipkdbfbyte) 107595719Sbenno_C_LABEL(ipkdbfbyte): 107695719Sbenno li 9,EXC_DSI /* establish new fault routine */ 107795719Sbenno lwz 5,0(9) 107895719Sbenno lis 6,ipkdbfault@ha 107995719Sbenno lwz 6,ipkdbfault@l(6) 108095719Sbenno stw 6,0(9) 108195719Sbenno#ifdef IPKDBUSERHACK 108295719Sbenno lis 8,_C_LABEL(ipkdbsr)@ha 108395719Sbenno lwz 8,_C_LABEL(ipkdbsr)@l(8) 108495719Sbenno mtsr USER_SR,8 108595719Sbenno isync 108695719Sbenno#endif 108795719Sbenno dcbst 0,9 /* flush data... */ 108895719Sbenno sync 108995719Sbenno icbi 0,9 /* and instruction caches */ 109095719Sbenno lbz 3,0(3) /* fetch data */ 109195719Sbenno stw 5,0(9) /* restore previous fault handler */ 109295719Sbenno dcbst 0,9 /* and flush data... */ 109395719Sbenno sync 109495719Sbenno icbi 0,9 /* and instruction caches */ 109595719Sbenno blr 109695719Sbenno 109795719Sbenno/* 109895719Sbenno * int ipkdbsbyte(unsigned char *p, int c) 109995719Sbenno */ 110095719Sbenno .globl _C_LABEL(ipkdbsbyte) 110195719Sbenno_C_LABEL(ipkdbsbyte): 110295719Sbenno li 9,EXC_DSI /* establish new fault routine */ 110395719Sbenno lwz 5,0(9) 110495719Sbenno lis 6,ipkdbfault@ha 110595719Sbenno lwz 6,ipkdbfault@l(6) 110695719Sbenno stw 6,0(9) 110795719Sbenno#ifdef IPKDBUSERHACK 110895719Sbenno lis 8,_C_LABEL(ipkdbsr)@ha 110995719Sbenno lwz 8,_C_LABEL(ipkdbsr)@l(8) 111095719Sbenno mtsr USER_SR,8 111195719Sbenno isync 111295719Sbenno#endif 111395719Sbenno dcbst 0,9 /* flush data... */ 111495719Sbenno sync 111595719Sbenno icbi 0,9 /* and instruction caches */ 111695719Sbenno mr 6,3 111795719Sbenno xor 3,3,3 111895719Sbenno stb 4,0(6) 111995719Sbenno dcbst 0,6 /* Now do appropriate flushes 112095719Sbenno to data... */ 112195719Sbenno sync 112295719Sbenno icbi 0,6 /* and instruction caches */ 112395719Sbenno stw 5,0(9) /* restore previous fault handler */ 112495719Sbenno dcbst 0,9 /* and flush data... */ 112595719Sbenno sync 112695719Sbenno icbi 0,9 /* and instruction caches */ 112795719Sbenno blr 112895719Sbenno#endif /* IPKDB */ 1129