trap_subr64.S revision 222620
195719Sbenno/* $FreeBSD: head/sys/powerpc/aim/trap_subr64.S 222620 2011-06-02 14:25:52Z nwhitehorn $ */ 295719Sbenno/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ 395719Sbenno 4139825Simp/*- 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 * 39174599Smarcel * #include <powerpc/aim/trap_subr.S> 4095719Sbenno */ 4195719Sbenno 4295719Sbenno/* 43125441Sgrehan * Save/restore segment registers 4495719Sbenno */ 4595719Sbenno 4695719Sbenno/* 47209975Snwhitehorn * Restore SRs for a pmap 48209975Snwhitehorn * 49209975Snwhitehorn * Requires that r28-r31 be scratch, with r28 initialized to the SLB cache 50209975Snwhitehorn */ 51209975Snwhitehorn 52212722Snwhitehorn/* 53212722Snwhitehorn * User SRs are loaded through a pointer to the current pmap. 54212722Snwhitehorn */ 55212722Snwhitehornrestore_usersrs: 56222620Snwhitehorn GET_CPUINFO(%r28) 57222620Snwhitehorn ld %r28,PC_USERSLB(%r28) 58209975Snwhitehorn li %r29, 0 /* Set the counter to zero */ 59209975Snwhitehorn 60209975Snwhitehorn slbia 61209975Snwhitehorn slbmfee %r31,%r29 62209975Snwhitehorn clrrdi %r31,%r31,28 63209975Snwhitehorn slbie %r31 64222620Snwhitehorn1: ld %r31, 0(%r28) /* Load SLB entry pointer */ 65222620Snwhitehorn cmpli 0, %r31, 0 /* If NULL, stop */ 66222620Snwhitehorn beqlr 67209975Snwhitehorn 68212722Snwhitehorn ld %r30, 0(%r31) /* Load SLBV */ 69212722Snwhitehorn ld %r31, 8(%r31) /* Load SLBE */ 70212722Snwhitehorn or %r31, %r31, %r29 /* Set SLBE slot */ 71222620Snwhitehorn slbmte %r30, %r31 /* Install SLB entry */ 72209975Snwhitehorn 73222620Snwhitehorn addi %r28, %r28, 8 /* Advance pointer */ 74222620Snwhitehorn addi %r29, %r29, 1 75222620Snwhitehorn b 1b /* Repeat */ 76209975Snwhitehorn 77209975Snwhitehorn/* 78212722Snwhitehorn * Kernel SRs are loaded directly from the PCPU fields 7995719Sbenno */ 80212722Snwhitehornrestore_kernsrs: 81222620Snwhitehorn GET_CPUINFO(%r28) 82222620Snwhitehorn addi %r28,%r28,PC_KERNSLB 83212722Snwhitehorn li %r29, 0 /* Set the counter to zero */ 8495719Sbenno 85212722Snwhitehorn slbia 86212722Snwhitehorn slbmfee %r31,%r29 87212722Snwhitehorn clrrdi %r31,%r31,28 88212722Snwhitehorn slbie %r31 89222620Snwhitehorn1: cmpli 0, %r29, USER_SLB_SLOT /* Skip the user slot */ 90222620Snwhitehorn beq- 2f 9195719Sbenno 92222620Snwhitehorn ld %r31, 8(%r28) /* Load SLBE */ 93222620Snwhitehorn cmpli 0, %r31, 0 /* If SLBE is not valid, stop */ 94222620Snwhitehorn beqlr 95212722Snwhitehorn ld %r30, 0(%r28) /* Load SLBV */ 96222620Snwhitehorn slbmte %r30, %r31 /* Install SLB entry */ 97212722Snwhitehorn 98222620Snwhitehorn2: addi %r28, %r28, 16 /* Advance pointer */ 99222620Snwhitehorn addi %r29, %r29, 1 100222620Snwhitehorn cmpli 0, %r29, 64 /* Repeat if we are not at the end */ 101222620Snwhitehorn blt 1b 102222620Snwhitehorn blr 103212722Snwhitehorn 104125441Sgrehan/* 105125441Sgrehan * FRAME_SETUP assumes: 106125441Sgrehan * SPRG1 SP (1) 107188860Snwhitehorn * SPRG3 trap type 108209975Snwhitehorn * savearea r27-r31,DAR,DSISR (DAR & DSISR only for DSI traps) 109125441Sgrehan * r28 LR 110125441Sgrehan * r29 CR 111125441Sgrehan * r30 scratch 112125441Sgrehan * r31 scratch 113125441Sgrehan * r1 kernel stack 114125441Sgrehan * SRR0/1 as at start of trap 115125441Sgrehan */ 116125441Sgrehan#define FRAME_SETUP(savearea) \ 117125441Sgrehan/* Have to enable translation to allow access of kernel stack: */ \ 118125441Sgrehan GET_CPUINFO(%r31); \ 119125441Sgrehan mfsrr0 %r30; \ 120209975Snwhitehorn std %r30,(savearea+CPUSAVE_SRR0)(%r31); /* save SRR0 */ \ 121125441Sgrehan mfsrr1 %r30; \ 122209975Snwhitehorn std %r30,(savearea+CPUSAVE_SRR1)(%r31); /* save SRR1 */ \ 123125441Sgrehan mfmsr %r30; \ 124125441Sgrehan ori %r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */ \ 125125441Sgrehan mtmsr %r30; /* stack can now be accessed */ \ 126125441Sgrehan isync; \ 127125441Sgrehan mfsprg1 %r31; /* get saved SP */ \ 128209975Snwhitehorn stdu %r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \ 129209975Snwhitehorn std %r0, FRAME_0+48(%r1); /* save r0 in the trapframe */ \ 130209975Snwhitehorn std %r31,FRAME_1+48(%r1); /* save SP " " */ \ 131209975Snwhitehorn std %r2, FRAME_2+48(%r1); /* save r2 " " */ \ 132209975Snwhitehorn std %r28,FRAME_LR+48(%r1); /* save LR " " */ \ 133209975Snwhitehorn std %r29,FRAME_CR+48(%r1); /* save CR " " */ \ 134125441Sgrehan GET_CPUINFO(%r2); \ 135209975Snwhitehorn ld %r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */ \ 136209975Snwhitehorn ld %r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */ \ 137209975Snwhitehorn ld %r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */ \ 138209975Snwhitehorn ld %r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \ 139209975Snwhitehorn ld %r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \ 140209975Snwhitehorn std %r3, FRAME_3+48(%r1); /* save r3-r31 */ \ 141209975Snwhitehorn std %r4, FRAME_4+48(%r1); \ 142209975Snwhitehorn std %r5, FRAME_5+48(%r1); \ 143209975Snwhitehorn std %r6, FRAME_6+48(%r1); \ 144209975Snwhitehorn std %r7, FRAME_7+48(%r1); \ 145209975Snwhitehorn std %r8, FRAME_8+48(%r1); \ 146209975Snwhitehorn std %r9, FRAME_9+48(%r1); \ 147209975Snwhitehorn std %r10, FRAME_10+48(%r1); \ 148209975Snwhitehorn std %r11, FRAME_11+48(%r1); \ 149209975Snwhitehorn std %r12, FRAME_12+48(%r1); \ 150209975Snwhitehorn std %r13, FRAME_13+48(%r1); \ 151209975Snwhitehorn std %r14, FRAME_14+48(%r1); \ 152209975Snwhitehorn std %r15, FRAME_15+48(%r1); \ 153209975Snwhitehorn std %r16, FRAME_16+48(%r1); \ 154209975Snwhitehorn std %r17, FRAME_17+48(%r1); \ 155209975Snwhitehorn std %r18, FRAME_18+48(%r1); \ 156209975Snwhitehorn std %r19, FRAME_19+48(%r1); \ 157209975Snwhitehorn std %r20, FRAME_20+48(%r1); \ 158209975Snwhitehorn std %r21, FRAME_21+48(%r1); \ 159209975Snwhitehorn std %r22, FRAME_22+48(%r1); \ 160209975Snwhitehorn std %r23, FRAME_23+48(%r1); \ 161209975Snwhitehorn std %r24, FRAME_24+48(%r1); \ 162209975Snwhitehorn std %r25, FRAME_25+48(%r1); \ 163209975Snwhitehorn std %r26, FRAME_26+48(%r1); \ 164209975Snwhitehorn std %r27, FRAME_27+48(%r1); \ 165209975Snwhitehorn std %r28, FRAME_28+48(%r1); \ 166209975Snwhitehorn std %r29, FRAME_29+48(%r1); \ 167209975Snwhitehorn std %r30, FRAME_30+48(%r1); \ 168209975Snwhitehorn std %r31, FRAME_31+48(%r1); \ 169209975Snwhitehorn ld %r28,(savearea+CPUSAVE_AIM_DAR)(%r2); /* saved DAR */ \ 170209975Snwhitehorn ld %r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\ 171209975Snwhitehorn ld %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \ 172209975Snwhitehorn ld %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \ 173125441Sgrehan mfxer %r3; \ 174125441Sgrehan mfctr %r4; \ 175188860Snwhitehorn mfsprg3 %r5; \ 176209975Snwhitehorn std %r3, FRAME_XER+48(1); /* save xer/ctr/exc */ \ 177209975Snwhitehorn std %r4, FRAME_CTR+48(1); \ 178209975Snwhitehorn std %r5, FRAME_EXC+48(1); \ 179209975Snwhitehorn std %r28,FRAME_AIM_DAR+48(1); \ 180209975Snwhitehorn std %r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */ \ 181209975Snwhitehorn std %r30,FRAME_SRR0+48(1); \ 182209975Snwhitehorn std %r31,FRAME_SRR1+48(1) 18395719Sbenno 184125441Sgrehan#define FRAME_LEAVE(savearea) \ 185125441Sgrehan/* Now restore regs: */ \ 186209975Snwhitehorn ld %r2,FRAME_SRR0+48(%r1); \ 187209975Snwhitehorn ld %r3,FRAME_SRR1+48(%r1); \ 188209975Snwhitehorn ld %r4,FRAME_CTR+48(%r1); \ 189209975Snwhitehorn ld %r5,FRAME_XER+48(%r1); \ 190209975Snwhitehorn ld %r6,FRAME_LR+48(%r1); \ 191125441Sgrehan GET_CPUINFO(%r7); \ 192209975Snwhitehorn std %r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */ \ 193209975Snwhitehorn std %r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */ \ 194209975Snwhitehorn ld %r7,FRAME_CR+48(%r1); \ 195125441Sgrehan mtctr %r4; \ 196125441Sgrehan mtxer %r5; \ 197125441Sgrehan mtlr %r6; \ 198125441Sgrehan mtsprg1 %r7; /* save cr */ \ 199209975Snwhitehorn ld %r31,FRAME_31+48(%r1); /* restore r0-31 */ \ 200209975Snwhitehorn ld %r30,FRAME_30+48(%r1); \ 201209975Snwhitehorn ld %r29,FRAME_29+48(%r1); \ 202209975Snwhitehorn ld %r28,FRAME_28+48(%r1); \ 203209975Snwhitehorn ld %r27,FRAME_27+48(%r1); \ 204209975Snwhitehorn ld %r26,FRAME_26+48(%r1); \ 205209975Snwhitehorn ld %r25,FRAME_25+48(%r1); \ 206209975Snwhitehorn ld %r24,FRAME_24+48(%r1); \ 207209975Snwhitehorn ld %r23,FRAME_23+48(%r1); \ 208209975Snwhitehorn ld %r22,FRAME_22+48(%r1); \ 209209975Snwhitehorn ld %r21,FRAME_21+48(%r1); \ 210209975Snwhitehorn ld %r20,FRAME_20+48(%r1); \ 211209975Snwhitehorn ld %r19,FRAME_19+48(%r1); \ 212209975Snwhitehorn ld %r18,FRAME_18+48(%r1); \ 213209975Snwhitehorn ld %r17,FRAME_17+48(%r1); \ 214209975Snwhitehorn ld %r16,FRAME_16+48(%r1); \ 215209975Snwhitehorn ld %r15,FRAME_15+48(%r1); \ 216209975Snwhitehorn ld %r14,FRAME_14+48(%r1); \ 217209975Snwhitehorn ld %r13,FRAME_13+48(%r1); \ 218209975Snwhitehorn ld %r12,FRAME_12+48(%r1); \ 219209975Snwhitehorn ld %r11,FRAME_11+48(%r1); \ 220209975Snwhitehorn ld %r10,FRAME_10+48(%r1); \ 221209975Snwhitehorn ld %r9, FRAME_9+48(%r1); \ 222209975Snwhitehorn ld %r8, FRAME_8+48(%r1); \ 223209975Snwhitehorn ld %r7, FRAME_7+48(%r1); \ 224209975Snwhitehorn ld %r6, FRAME_6+48(%r1); \ 225209975Snwhitehorn ld %r5, FRAME_5+48(%r1); \ 226209975Snwhitehorn ld %r4, FRAME_4+48(%r1); \ 227209975Snwhitehorn ld %r3, FRAME_3+48(%r1); \ 228209975Snwhitehorn ld %r2, FRAME_2+48(%r1); \ 229209975Snwhitehorn ld %r0, FRAME_0+48(%r1); \ 230209975Snwhitehorn ld %r1, FRAME_1+48(%r1); \ 231125441Sgrehan/* Can't touch %r1 from here on */ \ 232125441Sgrehan mtsprg2 %r2; /* save r2 & r3 */ \ 233125441Sgrehan mtsprg3 %r3; \ 234125441Sgrehan/* Disable translation, machine check and recoverability: */ \ 235125441Sgrehan mfmsr %r2; \ 236125441Sgrehan andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \ 237125441Sgrehan mtmsr %r2; \ 238125441Sgrehan isync; \ 239125441Sgrehan/* Decide whether we return to user mode: */ \ 240125441Sgrehan GET_CPUINFO(%r2); \ 241209975Snwhitehorn ld %r3,(savearea+CPUSAVE_SRR1)(%r2); \ 242125441Sgrehan mtcr %r3; \ 243125441Sgrehan bf 17,1f; /* branch if PSL_PR is false */ \ 244125441Sgrehan/* Restore user SRs */ \ 245209975Snwhitehorn GET_CPUINFO(%r3); \ 246209975Snwhitehorn std %r27,(savearea+CPUSAVE_R27)(%r3); \ 247209975Snwhitehorn std %r28,(savearea+CPUSAVE_R28)(%r3); \ 248209975Snwhitehorn std %r29,(savearea+CPUSAVE_R29)(%r3); \ 249209975Snwhitehorn std %r30,(savearea+CPUSAVE_R30)(%r3); \ 250209975Snwhitehorn std %r31,(savearea+CPUSAVE_R31)(%r3); \ 251209975Snwhitehorn mflr %r27; /* preserve LR */ \ 252212722Snwhitehorn bl restore_usersrs; /* uses r28-r31 */ \ 253209975Snwhitehorn mtlr %r27; \ 254209975Snwhitehorn ld %r31,(savearea+CPUSAVE_R31)(%r3); \ 255209975Snwhitehorn ld %r30,(savearea+CPUSAVE_R30)(%r3); \ 256209975Snwhitehorn ld %r29,(savearea+CPUSAVE_R29)(%r3); \ 257209975Snwhitehorn ld %r28,(savearea+CPUSAVE_R28)(%r3); \ 258209975Snwhitehorn ld %r27,(savearea+CPUSAVE_R27)(%r3); \ 259125441Sgrehan1: mfsprg1 %r2; /* restore cr */ \ 260125441Sgrehan mtcr %r2; \ 261125441Sgrehan GET_CPUINFO(%r2); \ 262209975Snwhitehorn ld %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \ 263125441Sgrehan mtsrr0 %r3; \ 264209975Snwhitehorn ld %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \ 265125441Sgrehan mtsrr1 %r3; \ 266125441Sgrehan mfsprg2 %r2; /* restore r2 & r3 */ \ 267125441Sgrehan mfsprg3 %r3 26895719Sbenno 269178628Smarcel#ifdef SMP 27095719Sbenno/* 271178628Smarcel * Processor reset exception handler. These are typically 272178628Smarcel * the first instructions the processor executes after a 273198400Snwhitehorn * software reset. We do this in two bits so that we are 274198400Snwhitehorn * not still hanging around in the trap handling region 275198400Snwhitehorn * once the MMU is turned on. 276132571Sgrehan */ 277178628Smarcel .globl CNAME(rstcode), CNAME(rstsize) 278178628SmarcelCNAME(rstcode): 279209975Snwhitehorn /* Explicitly set MSR[SF] */ 280209975Snwhitehorn mfmsr %r9 281209975Snwhitehorn li %r8,1 282209975Snwhitehorn insrdi %r9,%r8,1,0 283209975Snwhitehorn mtmsrd %r9 284209975Snwhitehorn isync 285209975Snwhitehorn 286198400Snwhitehorn ba cpu_reset 287198400SnwhitehornCNAME(rstsize) = . - CNAME(rstcode) 288198400Snwhitehorn 289198400Snwhitehorncpu_reset: 290209975Snwhitehorn lis %r1,(tmpstk+TMPSTKSZ-48)@ha /* get new SP */ 291209975Snwhitehorn addi %r1,%r1,(tmpstk+TMPSTKSZ-48)@l 292178628Smarcel 293209975Snwhitehorn lis %r3,tocbase@ha 294209975Snwhitehorn ld %r2,tocbase@l(%r3) 295183060Smarcel lis %r3,1@l 296218824Snwhitehorn bl CNAME(cpudep_ap_early_bootstrap) /* Set PCPU */ 297209975Snwhitehorn nop 298218824Snwhitehorn bl CNAME(pmap_cpu_bootstrap) /* Turn on virtual memory */ 299209975Snwhitehorn nop 300218824Snwhitehorn bl CNAME(cpudep_ap_bootstrap) /* Set up PCPU and stack */ 301209975Snwhitehorn nop 302209975Snwhitehorn mr %r1,%r3 /* Use new stack */ 303218824Snwhitehorn bl CNAME(machdep_ap_bootstrap) /* And away! */ 304209975Snwhitehorn nop 305178628Smarcel 306178628Smarcel /* Should not be reached */ 307178628Smarcel9: 308178628Smarcel b 9b 309132571Sgrehan#endif 310132571Sgrehan 311132571Sgrehan/* 31295719Sbenno * This code gets copied to all the trap vectors 313125441Sgrehan * (except ISI/DSI, ALI, and the interrupts) 31495719Sbenno */ 315178628Smarcel 31696773Sbenno .globl CNAME(trapcode),CNAME(trapsize) 31796773SbennoCNAME(trapcode): 318125441Sgrehan mtsprg1 %r1 /* save SP */ 319188860Snwhitehorn mflr %r1 /* Save the old LR in r1 */ 320188860Snwhitehorn mtsprg2 %r1 /* And then in SPRG2 */ 321209975Snwhitehorn li %r1, 0xA0 /* How to get the vector from LR */ 322188860Snwhitehorn bla generictrap /* LR & SPRG3 is exception # */ 32396773SbennoCNAME(trapsize) = .-CNAME(trapcode) 32495719Sbenno 32595719Sbenno/* 32695719Sbenno * For ALI: has to save DSISR and DAR 32795719Sbenno */ 32896773Sbenno .globl CNAME(alitrap),CNAME(alisize) 32996773SbennoCNAME(alitrap): 330125441Sgrehan mtsprg1 %r1 /* save SP */ 331125441Sgrehan GET_CPUINFO(%r1) 332209975Snwhitehorn std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */ 333209975Snwhitehorn std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 334209975Snwhitehorn std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 335209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 336209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 337125441Sgrehan mfdar %r30 338125441Sgrehan mfdsisr %r31 339209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) 340209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) 341125441Sgrehan mfsprg1 %r1 /* restore SP, in case of branch */ 342125441Sgrehan mflr %r28 /* save LR */ 343125441Sgrehan mfcr %r29 /* save CR */ 344188860Snwhitehorn 345188951Snwhitehorn /* Put our exception vector in SPRG3 */ 346188860Snwhitehorn li %r31, EXC_ALI 347188860Snwhitehorn mtsprg3 %r31 348188860Snwhitehorn 349188860Snwhitehorn /* Test whether we already had PR set */ 350125441Sgrehan mfsrr1 %r31 351125441Sgrehan mtcr %r31 352188860Snwhitehorn bla s_trap 35396773SbennoCNAME(alisize) = .-CNAME(alitrap) 35495719Sbenno 35595719Sbenno/* 35695719Sbenno * Similar to the above for DSI 35795719Sbenno * Has to handle BAT spills 35895719Sbenno * and standard pagetable spills 35995719Sbenno */ 36096773Sbenno .globl CNAME(dsitrap),CNAME(dsisize) 36196773SbennoCNAME(dsitrap): 362125441Sgrehan mtsprg1 %r1 /* save SP */ 363125441Sgrehan GET_CPUINFO(%r1) 364209975Snwhitehorn std %r27,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */ 365209975Snwhitehorn std %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) 366209975Snwhitehorn std %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) 367209975Snwhitehorn std %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) 368209975Snwhitehorn std %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) 369125441Sgrehan mfsprg1 %r1 /* restore SP */ 370125441Sgrehan mfcr %r29 /* save CR */ 371125441Sgrehan mfxer %r30 /* save XER */ 372125441Sgrehan mtsprg2 %r30 /* in SPRG2 */ 373125441Sgrehan mfsrr1 %r31 /* test kernel mode */ 374125441Sgrehan mtcr %r31 375125441Sgrehan mflr %r28 /* save LR (SP already saved) */ 376125441Sgrehan bla disitrap 37796773SbennoCNAME(dsisize) = .-CNAME(dsitrap) 37895719Sbenno 37995719Sbenno/* 38095719Sbenno * Preamble code for DSI/ISI traps 38195719Sbenno */ 38295719Sbennodisitrap: 383188951Snwhitehorn /* Write the trap vector to SPRG3 by computing LR & 0xff00 */ 384188860Snwhitehorn mflr %r1 385188860Snwhitehorn andi. %r1,%r1,0xff00 386188860Snwhitehorn mtsprg3 %r1 387188860Snwhitehorn 388125441Sgrehan GET_CPUINFO(%r1) 389209975Snwhitehorn ld %r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) 390209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) 391209975Snwhitehorn ld %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) 392209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 393209975Snwhitehorn ld %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) 394209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 395209975Snwhitehorn ld %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) 396209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 397209975Snwhitehorn ld %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) 398209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 399125441Sgrehan mfdar %r30 400125441Sgrehan mfdsisr %r31 401209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) 402209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) 403125441Sgrehan 404132571Sgrehan#ifdef KDB 405132571Sgrehan /* Try and detect a kernel stack overflow */ 406132571Sgrehan mfsrr1 %r31 407132571Sgrehan mtcr %r31 408132571Sgrehan bt 17,realtrap /* branch is user mode */ 409132571Sgrehan mfsprg1 %r31 /* get old SP */ 410132571Sgrehan sub. %r30,%r31,%r30 /* SP - DAR */ 411132571Sgrehan bge 1f 412132571Sgrehan neg %r30,%r30 /* modulo value */ 413209975Snwhitehorn1: cmpldi %cr0,%r30,4096 /* is DAR within a page of SP? */ 414132571Sgrehan bge %cr0,realtrap /* no, too far away. */ 415132571Sgrehan 416132571Sgrehan /* Now convert this DSI into a DDB trap. */ 417132571Sgrehan GET_CPUINFO(%r1) 418209975Snwhitehorn ld %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */ 419209975Snwhitehorn std %r30,(PC_DBSAVE +CPUSAVE_AIM_DAR)(%r1) /* save DAR */ 420209975Snwhitehorn ld %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */ 421209975Snwhitehorn std %r30,(PC_DBSAVE +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */ 422209975Snwhitehorn ld %r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get r27 */ 423209975Snwhitehorn std %r31,(PC_DBSAVE +CPUSAVE_R27)(%r1) /* save r27 */ 424209975Snwhitehorn ld %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get r28 */ 425209975Snwhitehorn std %r30,(PC_DBSAVE +CPUSAVE_R28)(%r1) /* save r28 */ 426209975Snwhitehorn ld %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get r29 */ 427209975Snwhitehorn std %r31,(PC_DBSAVE +CPUSAVE_R29)(%r1) /* save r29 */ 428209975Snwhitehorn ld %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get r30 */ 429209975Snwhitehorn std %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */ 430209975Snwhitehorn ld %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */ 431209975Snwhitehorn std %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */ 432191039Snwhitehorn b dbtrap 433132571Sgrehan#endif 434132571Sgrehan 435125441Sgrehan /* XXX need stack probe here */ 43695719Sbennorealtrap: 43795719Sbenno/* Test whether we already had PR set */ 438125441Sgrehan mfsrr1 %r1 439125441Sgrehan mtcr %r1 440125441Sgrehan mfsprg1 %r1 /* restore SP (might have been 44195719Sbenno overwritten) */ 442188860Snwhitehorn bf 17,k_trap /* branch if PSL_PR is false */ 443188860Snwhitehorn GET_CPUINFO(%r1) 444209975Snwhitehorn ld %r1,PC_CURPCB(%r1) 445209975Snwhitehorn mr %r27,%r28 /* Save LR, r29 */ 446209975Snwhitehorn mtsprg2 %r29 447212722Snwhitehorn bl restore_kernsrs /* enable kernel mapping */ 448209975Snwhitehorn mfsprg2 %r29 449209975Snwhitehorn mr %r28,%r27 450188860Snwhitehorn ba s_trap 451188860Snwhitehorn 452188860Snwhitehorn/* 453188860Snwhitehorn * generictrap does some standard setup for trap handling to minimize 454188860Snwhitehorn * the code that need be installed in the actual vectors. It expects 455188860Snwhitehorn * the following conditions. 456188860Snwhitehorn * 457188860Snwhitehorn * R1 - Trap vector = LR & (0xff00 | R1) 458188860Snwhitehorn * SPRG1 - Original R1 contents 459188860Snwhitehorn * SPRG2 - Original LR 460188860Snwhitehorn */ 461188860Snwhitehorn 462188860Snwhitehorngenerictrap: 463188860Snwhitehorn /* Save R1 for computing the exception vector */ 464188860Snwhitehorn mtsprg3 %r1 465188860Snwhitehorn 466188860Snwhitehorn /* Save interesting registers */ 467188860Snwhitehorn GET_CPUINFO(%r1) 468209975Snwhitehorn std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */ 469209975Snwhitehorn std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 470209975Snwhitehorn std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 471209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 472209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 473209975Snwhitehorn mfdar %r30 474209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) 475188860Snwhitehorn mfsprg1 %r1 /* restore SP, in case of branch */ 476188860Snwhitehorn mfsprg2 %r28 /* save LR */ 477188860Snwhitehorn mfcr %r29 /* save CR */ 478188860Snwhitehorn 479188860Snwhitehorn /* Compute the exception vector from the link register */ 480188860Snwhitehorn mfsprg3 %r31 481188860Snwhitehorn ori %r31,%r31,0xff00 482188860Snwhitehorn mflr %r30 483188860Snwhitehorn and %r30,%r30,%r31 484188860Snwhitehorn mtsprg3 %r30 485188860Snwhitehorn 486188860Snwhitehorn /* Test whether we already had PR set */ 487188860Snwhitehorn mfsrr1 %r31 488188860Snwhitehorn mtcr %r31 489188860Snwhitehorn 490125441Sgrehans_trap: 491125441Sgrehan bf 17,k_trap /* branch if PSL_PR is false */ 492125441Sgrehan GET_CPUINFO(%r1) 493125441Sgrehanu_trap: 494209975Snwhitehorn ld %r1,PC_CURPCB(%r1) 495209975Snwhitehorn mr %r27,%r28 /* Save LR, r29 */ 496209975Snwhitehorn mtsprg2 %r29 497212722Snwhitehorn bl restore_kernsrs /* enable kernel mapping */ 498209975Snwhitehorn mfsprg2 %r29 499209975Snwhitehorn mr %r28,%r27 50095719Sbenno 50195719Sbenno/* 50295719Sbenno * Now the common trap catching code. 50395719Sbenno */ 504125441Sgrehank_trap: 505125441Sgrehan FRAME_SETUP(PC_TEMPSAVE) 50699032Sbenno/* Call C interrupt dispatcher: */ 50795719Sbennotrapagain: 508209975Snwhitehorn lis %r3,tocbase@ha 509209975Snwhitehorn ld %r2,tocbase@l(%r3) 510209975Snwhitehorn addi %r3,%r1,48 511218824Snwhitehorn bl CNAME(powerpc_interrupt) 512209975Snwhitehorn nop 513209975Snwhitehorn 514209975Snwhitehorn .globl CNAME(trapexit) /* backtrace code sentinel */ 51596773SbennoCNAME(trapexit): 51695719Sbenno/* Disable interrupts: */ 517125441Sgrehan mfmsr %r3 518125441Sgrehan andi. %r3,%r3,~PSL_EE@l 519125441Sgrehan mtmsr %r3 520222309Snwhitehorn isync 52195719Sbenno/* Test AST pending: */ 522209975Snwhitehorn ld %r5,FRAME_SRR1+48(%r1) 523125441Sgrehan mtcr %r5 524125441Sgrehan bf 17,1f /* branch if PSL_PR is false */ 52599032Sbenno 526125441Sgrehan GET_CPUINFO(%r3) /* get per-CPU pointer */ 527209975Snwhitehorn ld %r4, PC_CURTHREAD(%r3) /* deref to get curthread */ 528125441Sgrehan lwz %r4, TD_FLAGS(%r4) /* get thread flags value */ 529125441Sgrehan lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h 530125441Sgrehan ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l 531125441Sgrehan and. %r4,%r4,%r5 53295719Sbenno beq 1f 533125441Sgrehan mfmsr %r3 /* re-enable interrupts */ 534125441Sgrehan ori %r3,%r3,PSL_EE@l 535125441Sgrehan mtmsr %r3 53699032Sbenno isync 537209975Snwhitehorn lis %r3,tocbase@ha 538209975Snwhitehorn ld %r2,tocbase@l(%r3) 539209975Snwhitehorn addi %r3,%r1,48 540218824Snwhitehorn bl CNAME(ast) 541209975Snwhitehorn nop 542153685Sgrehan .globl CNAME(asttrapexit) /* backtrace code sentinel #2 */ 543153685SgrehanCNAME(asttrapexit): 54499032Sbenno b trapexit /* test ast ret value ? */ 54595719Sbenno1: 546125441Sgrehan FRAME_LEAVE(PC_TEMPSAVE) 547190681Snwhitehorn rfid 548190681Snwhitehorn 549132075Sgrehan#if defined(KDB) 55095719Sbenno/* 551132075Sgrehan * Deliberate entry to dbtrap 55295719Sbenno */ 553209975SnwhitehornASENTRY(breakpoint) 554125441Sgrehan mtsprg1 %r1 555125441Sgrehan mfmsr %r3 556125441Sgrehan mtsrr1 %r3 557125441Sgrehan andi. %r3,%r3,~(PSL_EE|PSL_ME)@l 558125441Sgrehan mtmsr %r3 /* disable interrupts */ 55995719Sbenno isync 560125441Sgrehan GET_CPUINFO(%r3) 561209975Snwhitehorn std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r3) 562209975Snwhitehorn std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r3) 563209975Snwhitehorn std %r29,(PC_DBSAVE+CPUSAVE_R29)(%r3) 564209975Snwhitehorn std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3) 565209975Snwhitehorn std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3) 566125441Sgrehan mflr %r28 567125441Sgrehan li %r29,EXC_BPT 568125441Sgrehan mtlr %r29 569125441Sgrehan mfcr %r29 570125441Sgrehan mtsrr0 %r28 57195719Sbenno 57295719Sbenno/* 573132075Sgrehan * Now the kdb trap catching code. 57495719Sbenno */ 575132075Sgrehandbtrap: 576188951Snwhitehorn /* Write the trap vector to SPRG3 by computing LR & 0xff00 */ 577188860Snwhitehorn mflr %r1 578188860Snwhitehorn andi. %r1,%r1,0xff00 579188860Snwhitehorn mtsprg3 %r1 580188860Snwhitehorn 581209975Snwhitehorn lis %r1,(tmpstk+TMPSTKSZ-48)@ha /* get new SP */ 582209975Snwhitehorn addi %r1,%r1,(tmpstk+TMPSTKSZ-48)@l 583188860Snwhitehorn 584132075Sgrehan FRAME_SETUP(PC_DBSAVE) 58595719Sbenno/* Call C trap code: */ 586209975Snwhitehorn lis %r3,tocbase@ha 587209975Snwhitehorn ld %r2,tocbase@l(%r3) 588209975Snwhitehorn addi %r3,%r1,48 589218824Snwhitehorn bl CNAME(db_trap_glue) 590209975Snwhitehorn nop 591125441Sgrehan or. %r3,%r3,%r3 592132075Sgrehan bne dbleave 593132075Sgrehan/* This wasn't for KDB, so switch to real trap: */ 594209975Snwhitehorn ld %r3,FRAME_EXC+48(%r1) /* save exception */ 595125441Sgrehan GET_CPUINFO(%r4) 596209975Snwhitehorn std %r3,(PC_DBSAVE+CPUSAVE_R31)(%r4) 597132075Sgrehan FRAME_LEAVE(PC_DBSAVE) 598125441Sgrehan mtsprg1 %r1 /* prepare for entrance to realtrap */ 599125441Sgrehan GET_CPUINFO(%r1) 600209975Snwhitehorn std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) 601209975Snwhitehorn std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 602209975Snwhitehorn std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 603209975Snwhitehorn std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 604209975Snwhitehorn std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 605125441Sgrehan mflr %r28 606125441Sgrehan mfcr %r29 607209975Snwhitehorn ld %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) 608190946Snwhitehorn mtsprg3 %r31 /* SPRG3 was clobbered by FRAME_LEAVE */ 609125441Sgrehan mfsprg1 %r1 61095719Sbenno b realtrap 611132075Sgrehandbleave: 612132075Sgrehan FRAME_LEAVE(PC_DBSAVE) 613209975Snwhitehorn rfid 61495719Sbenno 61595719Sbenno/* 616132075Sgrehan * In case of KDB we want a separate trap catcher for it 61795719Sbenno */ 618132075Sgrehan .globl CNAME(dblow),CNAME(dbsize) 619132075SgrehanCNAME(dblow): 620125441Sgrehan mtsprg1 %r1 /* save SP */ 621125441Sgrehan mtsprg2 %r29 /* save r29 */ 622125441Sgrehan mfcr %r29 /* save CR in r29 */ 623125441Sgrehan mfsrr1 %r1 624125441Sgrehan mtcr %r1 625125441Sgrehan bf 17,1f /* branch if privileged */ 626188860Snwhitehorn 627188860Snwhitehorn /* Unprivileged case */ 628188860Snwhitehorn mtcr %r29 /* put the condition register back */ 629188860Snwhitehorn mfsprg2 %r29 /* ... and r29 */ 630188860Snwhitehorn mflr %r1 /* save LR */ 631188860Snwhitehorn mtsprg2 %r1 /* And then in SPRG2 */ 632188860Snwhitehorn li %r1, 0 /* How to get the vector from LR */ 633188860Snwhitehorn 634188860Snwhitehorn bla generictrap /* and we look like a generic trap */ 635125441Sgrehan1: 636188860Snwhitehorn /* Privileged, so drop to KDB */ 637188860Snwhitehorn GET_CPUINFO(%r1) 638209975Snwhitehorn std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r1) /* free r27 */ 639209975Snwhitehorn std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */ 640125441Sgrehan mfsprg2 %r28 /* r29 holds cr... */ 641209975Snwhitehorn std %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */ 642209975Snwhitehorn std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */ 643209975Snwhitehorn std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */ 644125441Sgrehan mflr %r28 /* save LR */ 645132075Sgrehan bla dbtrap 646132075SgrehanCNAME(dbsize) = .-CNAME(dblow) 647132075Sgrehan#endif /* KDB */ 648