diff options
author | benno <benno@FreeBSD.org> | 2002-04-29 12:14:31 +0000 |
---|---|---|
committer | benno <benno@FreeBSD.org> | 2002-04-29 12:14:31 +0000 |
commit | 7b2f527b762ff7efbf18017fe8d715d4dc5ed89a (patch) | |
tree | 45a1ef1295e7ad8713b677cd19c22c066f8608eb | |
parent | 2715240fe7a7238d5caa38cf8f6fb16ee0755a5c (diff) | |
download | FreeBSD-src-7b2f527b762ff7efbf18017fe8d715d4dc5ed89a.zip FreeBSD-src-7b2f527b762ff7efbf18017fe8d715d4dc5ed89a.tar.gz |
Commit of stuff that's been sitting in my tree for a while.
Highlights include:
- New low-level trap code from NetBSD. The high level code still needs a lot
of work.
- Fixes for some pmap handling in thread switching.
- The kernel will now get to attempting to jump into init in user mode. There
are some pmap/trap issues which prevent it from actually getting there though.
Obtained from: NetBSD (parts)
-rw-r--r-- | sys/powerpc/aim/locore.S | 943 | ||||
-rw-r--r-- | sys/powerpc/aim/swtch.S | 27 | ||||
-rw-r--r-- | sys/powerpc/aim/trap_subr.S | 1128 | ||||
-rw-r--r-- | sys/powerpc/include/frame.h | 46 | ||||
-rw-r--r-- | sys/powerpc/include/pcpu.h | 5 | ||||
-rw-r--r-- | sys/powerpc/include/spr.h | 360 | ||||
-rw-r--r-- | sys/powerpc/powerpc/genassym.c | 45 | ||||
-rw-r--r-- | sys/powerpc/powerpc/locore.S | 943 | ||||
-rw-r--r-- | sys/powerpc/powerpc/locore.s | 943 | ||||
-rw-r--r-- | sys/powerpc/powerpc/sigcode.S | 54 | ||||
-rw-r--r-- | sys/powerpc/powerpc/swtch.S | 27 | ||||
-rw-r--r-- | sys/powerpc/powerpc/swtch.s | 27 | ||||
-rw-r--r-- | sys/powerpc/powerpc/trap_subr.S | 1128 |
13 files changed, 2845 insertions, 2831 deletions
diff --git a/sys/powerpc/aim/locore.S b/sys/powerpc/aim/locore.S index 29a3b9c..fa231e8 100644 --- a/sys/powerpc/aim/locore.S +++ b/sys/powerpc/aim/locore.S @@ -65,6 +65,7 @@ #include <machine/trap.h> #include <machine/param.h> #include <machine/sr.h> +#include <machine/spr.h> #include <machine/psl.h> #include <machine/asm.h> @@ -122,6 +123,9 @@ GLOBAL(ofmsr) GLOBAL(powersave) .long 0 +#define INTSTK 8192 /* 8K interrupt stack */ +#define SPILLSTK 4096 /* 4K spill stack */ + /* * File-scope for locore.S */ @@ -391,929 +395,6 @@ ofw_back: blr /* - * Data used during primary/secondary traps/interrupts - */ -#define tempsave 0x2e0 /* primary save area for trap handling */ -#define disisave 0x3e0 /* primary save area for dsi/isi traps */ - -#define INTSTK (8*1024) /* 8K interrupt stack */ - .data - .align 4 -intstk: - .space INTSTK /* interrupt stack */ - -GLOBAL(intr_depth) - .long -1 /* in-use marker */ - -#define SPILLSTK 1024 /* 1K spill stack */ - - .comm spillstk,SPILLSTK,8 - -/* - * This code gets copied to all the trap vectors - * (except ISI/DSI, ALI, the interrupts, and possibly the debugging - * traps when using IPKDB). - */ - .text - .globl trapcode,trapsize -trapcode: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 31 - mtcr 31 - bc 4,17,1f /* branch if PSL_PR is clear */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ -1: - bla s_trap -trapsize = .-trapcode - -/* - * For ALI: has to save DSISR and DAR - */ - .globl alitrap,alisize -alitrap: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mfdar 30 - mfdsisr 31 - stmw 30,tempsave+16(0) - mflr 28 /* save LR */ - mfcr 29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 31 - mtcr 31 - bc 4,17,1f /* branch if PSL_PR is clear */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ -1: - bla s_trap -alisize = .-alitrap - -/* - * Similar to the above for DSI - * Has to handle BAT spills - * and standard pagetable spills - */ - .globl dsitrap,dsisize -dsitrap: - stmw 28,disisave(0) /* free r28-r31 */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - mtsprg 2,30 /* in SPRG2 */ - mfsrr1 31 /* test kernel mode */ - mtcr 31 - bc 12,17,1f /* branch if PSL_PR is set */ - mfdar 31 /* get fault address */ - rlwinm 31,31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis 31,31,battable@ha - lwz 30,battable@l(31) - mtcr 30 - bc 4,30,1f /* branch if supervisor valid is - false */ - /* get batl */ - lwz 31,battable+4@l(31) -/* We randomly use the highest two bat registers here */ - mftb 28 - andi. 28,28,1 - bne 2f - mtdbatu 2,30 - mtdbatl 2,31 - b 3f -2: - mtdbatu 3,30 - mtdbatl 3,31 -3: - mfsprg 30,2 /* restore XER */ - mtxer 30 - mtcr 29 /* restore CR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ -1: - mflr 28 /* save LR */ - bla s_dsitrap -dsisize = .-dsitrap - -/* - * Similar to the above for ISI - */ - .globl isitrap,isisize -isitrap: - stmw 28,disisave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfsrr1 31 /* test kernel mode */ - mtcr 31 - bc 12,17,1f /* branch if PSL_PR is set */ - mfsrr0 31 /* get fault address */ - rlwinm 31,31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis 31,31,battable@ha - lwz 30,battable@l(31) - mtcr 30 - bc 4,30,1f /* branch if supervisor valid is - false */ - mtibatu 3,30 - - /* get batl */ - lwz 30,battable+4@l(31) - mtibatl 3,30 - - mtcr 29 /* restore CR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ -1: - bla s_isitrap -isisize = .-isitrap - -/* - * This one for the external interrupt handler. - */ - .globl extint,extsize -extint: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - lis 1,intstk+INTSTK@ha /* get interrupt stack */ - addi 1,1,intstk+INTSTK@l - lwz 31,0(1) /* were we already running on intstk? */ - addic. 31,31,1 - stw 31,0(1) - beq 1f - mfsprg 1,1 /* yes, get old SP */ -1: - ba extintr -extsize = .-extint - -/* - * And this one for the decrementer interrupt handler. - */ - .globl decrint,decrsize -decrint: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - lis 28,decrnest@ha - lwz 29,decrnest@l(28) - cmplwi 0,29,0 - bne 2f - li 29,1 - stw 29,decrnest@l(28) - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - lis 1,intstk+INTSTK@ha /* get interrupt stack */ - addi 1,1,intstk+INTSTK@l - lwz 31,0(1) /* were we already running on intstk? */ - addic. 31,31,1 - stw 31,0(1) - beq 1f - mfsprg 1,1 /* yes, get old SP */ -1: - ba decrintr -2: - lmw 28,tempsave(0) - rfi -decrsize = .-decrint - -/* - * Now the tlb software load for 603 processors: - * (Code essentially from the 603e User Manual, Chapter 5, but - * corrected a lot.) - */ -#define DMISS 976 -#define DCMP 977 -#define HASH1 978 -#define HASH2 979 -#define IMISS 980 -#define ICMP 981 -#define RPA 982 - - .globl tlbimiss,tlbimsize -tlbimiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,ICMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - andi. 3,1,8 /* check G-bit */ - bne 4f /* if guarded, take ISI */ - mtctr 0 /* restore counter */ - mfspr 0,IMISS /* get the miss address for the tlbli */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - ori 1,1,0x100 /* set the reference bit */ - mtspr RPA,1 /* set the pte */ - srwi 1,1,8 /* get byte 7 of pte */ - tlbli 0 /* load the itlb */ - stb 1,6(2) /* update page table */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -4: /* guarded */ - mfsrr1 3 - andi. 2,3,0xffff /* clean upper srr1 */ - oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ - b 6f -5: /* not found anywhere */ - mfsrr1 3 - andi. 2,3,0xffff /* clean upper srr1 */ - oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ -6: - mtctr 0 /* restore counter */ - mtsrr1 2 - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_ISI -tlbimsize = .-tlbimiss - - .globl tlbdlmiss,tlbdlmsize -tlbdlmiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,DCMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - mtctr 0 /* restore counter */ - mfspr 0,DMISS /* get the miss address for the tlbld */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - ori 1,1,0x100 /* set the reference bit */ - mtspr RPA,1 /* set the pte */ - srwi 1,1,8 /* get byte 7 of pte */ - tlbld 0 /* load the dtlb */ - stb 1,6(2) /* update page table */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -5: /* not found anywhere */ - mfsrr1 3 - lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ - mtctr 0 /* restore counter */ - andi. 2,3,0xffff /* clean upper srr1 */ - mtsrr1 2 - mtdsisr 1 /* load the dsisr */ - mfspr 1,DMISS /* get the miss address */ - mtdar 1 /* put in dar */ - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_DSI -tlbdlmsize = .-tlbdlmiss - - .globl tlbdsmiss,tlbdsmsize -tlbdsmiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,DCMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - andi. 3,1,0x80 /* check the C-bit */ - beq 4f -5: - mtctr 0 /* restore counter */ - mfspr 0,DMISS /* get the miss address for the tlbld */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - mtspr RPA,1 /* set the pte */ - tlbld 0 /* load the dtlb */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -4: /* found, but C-bit = 0 */ - rlwinm. 3,1,30,0,1 /* test PP */ - bge- 7f - andi. 3,1,1 - beq+ 8f -9: /* found, but protection violation (PP==00)*/ - mfsrr1 3 - lis 1,0xa000000@h /* indicate protection violation - on store */ - b 1f -7: /* found, PP=1x */ - mfspr 3,DMISS /* get the miss address */ - mfsrin 1,3 /* get the segment register */ - mfsrr1 3 - rlwinm 3,3,18,31,31 /* get PR-bit */ - rlwnm. 2,2,3,1,1 /* get the key */ - bne- 9b /* protection violation */ -8: /* found, set reference/change bits */ - lwz 1,4(2) /* reload tlb entry */ - ori 1,1,0x180 - sth 1,6(2) - b 5b -5: /* not found anywhere */ - mfsrr1 3 - lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ - /* dsisr<6> to flag store */ -1: - mtctr 0 /* restore counter */ - andi. 2,3,0xffff /* clean upper srr1 */ - mtsrr1 2 - mtdsisr 1 /* load the dsisr */ - mfspr 1,DMISS /* get the miss address */ - mtdar 1 /* put in dar */ - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_DSI -tlbdsmsize = .-tlbdsmiss - -#ifdef DDB -#define ddbsave 0xde0 /* primary save area for DDB */ -/* - * In case of DDB we want a separate trap catcher for it - */ - .local ddbstk - .comm ddbstk,INTSTK,8 /* ddb stack */ - - .globl ddblow,ddbsize -ddblow: - mtsprg 1,1 /* save SP */ - stmw 28,ddbsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - lis 1,ddbstk+INTSTK@ha /* get new SP */ - addi 1,1,ddbstk+INTSTK@l - bla ddbtrap -ddbsize = .-ddblow -#endif /* DDB */ - -#ifdef IPKDB -#define ipkdbsave 0xde0 /* primary save area for IPKDB */ -/* - * In case of IPKDB we want a separate trap catcher for it - */ - - .local ipkdbstk - .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ - - .globl ipkdblow,ipkdbsize -ipkdblow: - mtsprg 1,1 /* save SP */ - stmw 28,ipkdbsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - lis 1,ipkdbstk+INTSTK@ha /* get new SP */ - addi 1,1,ipkdbstk+INTSTK@l - bla ipkdbtrap -ipkdbsize = .-ipkdblow -#endif /* IPKDB */ - -/* - * FRAME_SETUP assumes: - * SPRG1 SP (1) - * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) - * 28 LR - * 29 CR - * 1 kernel stack - * LR trap type - * SRR0/1 as at start of trap - */ -#define FRAME_SETUP(savearea) \ -/* Have to enable translation to allow access of kernel stack: */ \ - mfsrr0 30; \ - mfsrr1 31; \ - stmw 30,savearea+24(0); \ - mfmsr 30; \ - ori 30,30,(PSL_DR|PSL_IR); \ - mtmsr 30; \ - isync; \ - mfsprg 31,1; \ - stwu 31,-FRAMELEN(1); \ - stw 0,FRAME_0+8(1); \ - stw 31,FRAME_1+8(1); \ - stw 28,FRAME_LR+8(1); \ - stw 29,FRAME_CR+8(1); \ - lmw 28,savearea(0); \ - stmw 2,FRAME_2+8(1); \ - lmw 28,savearea+16(0); \ - mfxer 3; \ - mfctr 4; \ - mflr 5; \ - andi. 5,5,0xff00; \ - stw 3,FRAME_XER+8(1); \ - stw 4,FRAME_CTR+8(1); \ - stw 5,FRAME_EXC+8(1); \ - stw 28,FRAME_DAR+8(1); \ - stw 29,FRAME_DSISR+8(1); \ - stw 30,FRAME_SRR0+8(1); \ - stw 31,FRAME_SRR1+8(1) - -#define FRAME_LEAVE(savearea) \ -/* Now restore regs: */ \ - lwz 2,FRAME_SRR0+8(1); \ - lwz 3,FRAME_SRR1+8(1); \ - lwz 4,FRAME_CTR+8(1); \ - lwz 5,FRAME_XER+8(1); \ - lwz 6,FRAME_LR+8(1); \ - lwz 7,FRAME_CR+8(1); \ - stw 2,savearea(0); \ - stw 3,savearea+4(0); \ - mtctr 4; \ - mtxer 5; \ - mtlr 6; \ - mtsprg 1,7; /* save cr */ \ - lmw 2,FRAME_2+8(1); \ - lwz 0,FRAME_0+8(1); \ - lwz 1,FRAME_1+8(1); \ - mtsprg 2,2; /* save r2 & r3 */ \ - mtsprg 3,3; \ -/* Disable translation, machine check and recoverability: */ \ - mfmsr 2; \ - andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ - mtmsr 2; \ - isync; \ -/* Decide whether we return to user mode: */ \ - lwz 3,savearea+4(0); \ - mtcr 3; \ - bc 4,17,1f; /* branch if PSL_PR is false */ \ -/* Restore user & kernel access SR: */ \ -/* lis 2,curpm@ha; get real address of pmap */ \ -/* lwz 2,curpm@l(2); */ \ -/* lwz 3,PM_USRSR(2); */ \ -/* mtsr USER_SR,3; */ \ -/* lwz 3,PM_KERNELSR(2); */ \ -/* mtsr KERNEL_SR,3; */ \ -1: mfsprg 2,1; /* restore cr */ \ - mtcr 2; \ - lwz 2,savearea(0); \ - lwz 3,savearea+4(0); \ - mtsrr0 2; \ - mtsrr1 3; \ - mfsprg 2,2; /* restore r2 & r3 */ \ - mfsprg 3,3 - -/* - * Preamble code for DSI/ISI traps - */ -disitrap: - lmw 30,disisave(0) - stmw 30,tempsave(0) - lmw 30,disisave+8(0) - stmw 30,tempsave+8(0) - mfdar 30 - mfdsisr 31 - stmw 30,tempsave+16(0) -realtrap: -/* Test whether we already had PR set */ - mfsrr1 1 - mtcr 1 - mfsprg 1,1 /* restore SP (might have been - overwritten) */ - bc 4,17,s_trap /* branch if PSL_PR is false */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ - -/* - * Now the common trap catching code. - */ -s_trap: -/* First have to enable KERNEL mapping */ - lis 31,KERNEL_SEGMENT@h - ori 31,31,KERNEL_SEGMENT@l - mtsr KERNEL_SR,31 - FRAME_SETUP(tempsave) -/* Now we can recover interrupts again: */ - mfmsr 7 - ori 7,7,(PSL_EE|PSL_FP|PSL_ME|PSL_RI)@l - mtmsr 7 - isync -/* Call C trap code: */ - addi 3,1,8 - mr 30,3 - bl trap - mr 3,30 - bl ast - FRAME_LEAVE(tempsave) - rfi - -/* - * DSI second stage fault handler - */ -s_dsitrap: - mfdsisr 31 /* test whether this may be a - spill fault */ - mtcr 31 - mtsprg 1,1 /* save SP */ - bc 4,1,disitrap /* branch if table miss is false */ - lis 1,spillstk+SPILLSTK@ha - addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ - stwu 1,-52(1) - stw 0,48(1) /* save non-volatile registers */ - stw 3,44(1) - stw 4,40(1) - stw 5,36(1) - stw 6,32(1) - stw 7,28(1) - stw 8,24(1) - stw 9,20(1) - stw 10,16(1) - stw 11,12(1) - stw 12,8(1) - mflr 30 /* save trap type */ - mfctr 31 /* & CTR */ - mfdar 3 -s_pte_spill: - bl pmap_pte_spill /* try a spill */ - or. 3,3,3 - mtctr 31 /* restore CTR */ - mtlr 30 /* and trap type */ - mfsprg 31,2 /* get saved XER */ - mtxer 31 /* restore XER */ - lwz 12,8(1) /* restore non-volatile registers */ - lwz 11,12(1) - lwz 10,16(1) - lwz 9,20(1) - lwz 8,24(1) - lwz 7,28(1) - lwz 6,32(1) - lwz 5,36(1) - lwz 4,40(1) - lwz 3,44(1) - lwz 0,48(1) - beq disitrap - mfsprg 1,1 /* restore SP */ - mtcr 29 /* restore CR */ - mtlr 28 /* restore LR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ - -/* - * ISI second stage fault handler - */ -s_isitrap: - mfsrr1 31 /* test whether this may be a - spill fault */ - mtcr 31 - mtsprg 1,1 /* save SP */ - bc 4,1,disitrap /* branch if table miss is false */ - lis 1,spillstk+SPILLSTK@ha - addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ - stwu 1,-52(1) - stw 0,48(1) /* save non-volatile registers */ - stw 3,44(1) - stw 4,40(1) - stw 5,36(1) - stw 6,32(1) - stw 7,28(1) - stw 8,24(1) - stw 9,20(1) - stw 10,16(1) - stw 11,12(1) - stw 12,8(1) - mfxer 30 /* save XER */ - mtsprg 2,30 - mflr 30 /* save trap type */ - mfctr 31 /* & ctr */ - mfsrr0 3 - b s_pte_spill /* above */ - -/* - * External interrupt second level handler - */ -#define INTRENTER \ -/* Save non-volatile registers: */ \ - stwu 1,-88(1); /* temporarily */ \ - stw 0,84(1); \ - mfsprg 0,1; /* get original SP */ \ - stw 0,0(1); /* and store it */ \ - stw 3,80(1); \ - stw 4,76(1); \ - stw 5,72(1); \ - stw 6,68(1); \ - stw 7,64(1); \ - stw 8,60(1); \ - stw 9,56(1); \ - stw 10,52(1); \ - stw 11,48(1); \ - stw 12,44(1); \ - stw 28,40(1); /* saved LR */ \ - stw 29,36(1); /* saved CR */ \ - stw 30,32(1); /* saved XER */ \ - lmw 28,tempsave(0); /* restore r28-r31 */ \ - mfctr 6; \ - lis 5,intr_depth@ha; \ - lwz 5,intr_depth@l(5); \ - mfsrr0 4; \ - mfsrr1 3; \ - stw 6,28(1); \ - stw 5,20(1); \ - stw 4,12(1); \ - stw 3,8(1); \ -/* interrupts are recoverable here, and enable translation */ \ - lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ - ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ - mtsr KERNEL_SR,3; \ - mfmsr 5; \ - ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ - mtmsr 5; \ - isync - - .globl extint_call -extintr: - INTRENTER -extint_call: - bl extint_call /* to be filled in later */ - -intr_exit: -/* Disable interrupts (should already be disabled) and MMU here: */ - mfmsr 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l - mtmsr 3 - isync -/* restore possibly overwritten registers: */ - lwz 12,44(1) - lwz 11,48(1) - lwz 10,52(1) - lwz 9,56(1) - lwz 8,60(1) - lwz 7,64(1) - lwz 6,8(1) - lwz 5,12(1) - lwz 4,28(1) - lwz 3,32(1) - mtsrr1 6 - mtsrr0 5 - mtctr 4 - mtxer 3 -/* Returning to user mode? */ - mtcr 6 /* saved SRR1 */ - bc 4,17,1f /* branch if PSL_PR is false */ - mfsprg 3,0 /* get pcpu */ - lwz 3,PC_CURPCB(3) /* get curpcb from pcpu */ - lwz 3,PCB_PMR(3) /* get pmap real address from curpcb */ - mtsr KERNEL_SR,3 -/* Setup for entry to realtrap: */ - lwz 3,0(1) /* get saved SP */ - mtsprg 1,3 -#if 0 /* XXX */ - li 6,EXC_AST -#endif - stmw 28,tempsave(0) /* establish tempsave again */ - mtlr 6 - lwz 28,40(1) /* saved LR */ - lwz 29,36(1) /* saved CR */ - lwz 6,68(1) - lwz 5,72(1) - lwz 4,76(1) - lwz 3,80(1) - lwz 0,84(1) - lis 30,intr_depth@ha /* adjust reentrancy count */ - lwz 31,intr_depth@l(30) - addi 31,31,-1 - stw 31,intr_depth@l(30) - b realtrap /* XXX: should call ast(frame ptr) */ -1: -/* Here is the normal exit of extintr: */ - lwz 5,36(1) - lwz 6,40(1) - mtcr 5 - mtlr 6 - lwz 6,68(1) - lwz 5,72(1) - lis 3,intr_depth@ha /* adjust reentrancy count */ - lwz 4,intr_depth@l(3) - addi 4,4,-1 - stw 4,intr_depth@l(3) - lwz 4,76(1) - lwz 3,80(1) - lwz 0,84(1) - lwz 1,0(1) - rfi - -/* - * Decrementer interrupt second level handler - */ -decrintr: - INTRENTER - addi 3,1,8 /* intr frame */ - bl decr_intr - lis 28,decrnest@ha - xor 29,29,29 - stw 29,decrnest@l(28) - b intr_exit - -#ifdef DDB -/* - * Deliberate entry to ddbtrap - */ - .globl ddb_trap -ddb_trap: - mtsprg 1,1 - mfmsr 3 - mtsrr1 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI)@l - mtmsr 3 /* disable interrupts */ - isync - stmw 28,ddbsave(0) - mflr 28 - li 29,EXC_BPT - mtlr 29 - mfcr 29 - mtsrr0 28 - -/* - * Now the ddb trap catching code. - */ -ddbtrap: - FRAME_SETUP(ddbsave) -/* Call C trap code: */ - addi 3,1,8 - bl ddb_trap_glue - or. 3,3,3 - bne ddbleave -/* This wasn't for DDB, so switch to real trap: */ - lwz 3,FRAME_EXC+8(1) /* save exception */ - stw 3,ddbsave+8(0) - FRAME_LEAVE(ddbsave) - mtsprg 1,1 /* prepare for entrance to realtrap */ - stmw 28,tempsave(0) - mflr 28 - mfcr 29 - lwz 31,ddbsave+8(0) - mtlr 31 - b realtrap -ddbleave: - FRAME_LEAVE(ddbsave) - rfi -#endif /* DDB */ - -#ifdef IPKDB -/* - * Deliberate entry to ipkdbtrap - */ - .globl ipkdb_trap -ipkdb_trap: - mtsprg 1,1 - mfmsr 3 - mtsrr1 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI)@l - mtmsr 3 /* disable interrupts */ - isync - stmw 28,ipkdbsave(0) - mflr 28 - li 29,EXC_BPT - mtlr 29 - mfcr 29 - mtsrr0 28 - -/* - * Now the ipkdb trap catching code. - */ -ipkdbtrap: - FRAME_SETUP(ipkdbsave) -/* Call C trap code: */ - addi 3,1,8 - bl ipkdb_trap_glue - or. 3,3,3 - bne ipkdbleave -/* This wasn't for IPKDB, so switch to real trap: */ - lwz 3,FRAME_EXC+8(1) /* save exception */ - stw 3,ipkdbsave+8(0) - FRAME_LEAVE(ipkdbsave) - mtsprg 1,1 /* prepare for entrance to realtrap */ - stmw 28,tempsave(0) - mflr 28 - mfcr 29 - lwz 31,ipkdbsave+8(0) - mtlr 31 - b realtrap -ipkdbleave: - FRAME_LEAVE(ipkdbsave) - rfi - -ipkdbfault: - ba _ipkdbfault -_ipkdbfault: - mfsrr0 3 - addi 3,3,4 - mtsrr0 3 - li 3,-1 - rfi - -/* - * int ipkdbfbyte(unsigned char *p) - */ - .globl ipkdbfbyte -ipkdbfbyte: - li 9,EXC_DSI /* establish new fault routine */ - lwz 5,0(9) - lis 6,ipkdbfault@ha - lwz 6,ipkdbfault@l(6) - stw 6,0(9) -#ifdef IPKDBUSERHACK - lis 8,ipkdbsr@ha - lwz 8,ipkdbsr@l(8) - mtsr USER_SR,8 - isync -#endif - dcbst 0,9 /* flush data... */ - sync - icbi 0,9 /* and instruction caches */ - lbz 3,0(3) /* fetch data */ - stw 5,0(9) /* restore previous fault handler */ - dcbst 0,9 /* and flush data... */ - sync - icbi 0,9 /* and instruction caches */ - blr - -/* - * int ipkdbsbyte(unsigned char *p, int c) - */ - .globl ipkdbsbyte -ipkdbsbyte: - li 9,EXC_DSI /* establish new fault routine */ - lwz 5,0(9) - lis 6,ipkdbfault@ha - lwz 6,ipkdbfault@l(6) - stw 6,0(9) -#ifdef IPKDBUSERHACK - lis 8,ipkdbsr@ha - lwz 8,ipkdbsr@l(8) - mtsr USER_SR,8 - isync -#endif - dcbst 0,9 /* flush data... */ - sync - icbi 0,9 /* and instruction caches */ - mr 6,3 - xor 3,3,3 - stb 4,0(6) - dcbst 0,6 /* Now do appropriate flushes - to data... */ - sync - icbi 0,6 /* and instruction caches */ - stw 5,0(9) /* restore previous fault handler */ - dcbst 0,9 /* and flush data... */ - sync - icbi 0,9 /* and instruction caches */ - blr -#endif /* IPKDB */ - -/* * int setfault() * * Similar to setjmp to setup for handling faults on accesses to user memory. @@ -1326,7 +407,8 @@ setfault: mflr 0 mfcr 12 mfsprg 4,0 - lwz 4,PC_CURPCB(4) + lwz 4,PC_CURTHREAD(4) + lwz 4,TD_PCB(4) stw 3,PCB_ONFAULT(4) stw 0,0(3) stw 1,4(3) @@ -1335,15 +417,4 @@ setfault: xor 3,3,3 blr -/* - * Signal "trampoline" code. - */ - .globl sigcode -sigcode: - b sys_exit -esigcode: - .data -GLOBAL(szsigcode) - .long esigcode-sigcode - .text - +#include <powerpc/powerpc/trap_subr.S> diff --git a/sys/powerpc/aim/swtch.S b/sys/powerpc/aim/swtch.S index afa1ba5..875328e 100644 --- a/sys/powerpc/aim/swtch.S +++ b/sys/powerpc/aim/swtch.S @@ -106,17 +106,29 @@ ENTRY(cpu_switch) mfsprg %r4,0 /* Get the pcpu pointer */ stw %r16,PC_CURTHREAD(%r4) /* Store new current thread */ - lwz %r4,TD_PCB(%r16) /* Grab the new PCB */ + lwz %r15,TD_PROC(%r16) /* Grab the current thread's proc */ + lwz %r15,P_VMSPACE(%r15) /* Grab the current proc's vmspace */ + lwz %r15,VM_PMAP(%r15) /* ... pmap */ + mr %r3,%r15 + bl pmap_kextract + cmpwi cr4,%r3,0 + bne cr4,.L2 + mr %r3,%r15 +.L2: + stw %r3,PC_CURPMAP(%r4) /* Store it */ + lwz %r16,TD_PCB(%r16) /* Grab the new PCB */ + stw %r16,PC_CURPCB(%r4) + mr %r4,%r16 #if 0 lwz %r29, PCB_FLAGS(%r4) /* Restore FPU regs if needed */ andi. %r9, %r29, 1 - beq .L2 + beq .L3 mr %r3, %r4 bl enable_fpu #endif -.L2: +.L3: lmw %r14,PCB_CONTEXT(%r4) /* Load the non-volatile GP regs */ lwz %r5,PCB_CR(%r4) /* Load the condition register */ mtcr %r5 @@ -140,8 +152,9 @@ ENTRY(savectx) * Set up the return from cpu_fork() */ ENTRY(fork_trampoline) - lwz %r3,CF_FUNC(1) - lwz %r4,CF_ARG0(1) - lwz %r5,CF_ARG1(1) + lwz %r3,CF_FUNC(%r1) + lwz %r4,CF_ARG0(%r1) + lwz %r5,CF_ARG1(%r1) bl fork_exit - rfi + addi %r1,%r1,4 + b trapexit diff --git a/sys/powerpc/aim/trap_subr.S b/sys/powerpc/aim/trap_subr.S new file mode 100644 index 0000000..f348768 --- /dev/null +++ b/sys/powerpc/aim/trap_subr.S @@ -0,0 +1,1128 @@ +/* $FreeBSD$ */ +/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NOTICE: This is not a standalone file. to use it, #include it in + * your port's locore.S, like so: + * + * #include <powerpc/powerpc/trap_subr.S> + */ + +/* + * XXX Fake AST trap vector. This is here until we work out how to safely + * remove the AST code. + */ +#define EXC_AST 0x3000 + .data + .align 4 +astpending: + .long 0 + +/* + * Data used during primary/secondary traps/interrupts + */ +#define tempsave EXC_MCHK+0xe0 /* primary save area for trap handling */ +#define disisave EXC_DSI+0xe0 /* primary save area for dsi/isi traps */ + +/* + * XXX Interrupt and spill stacks need to be per-CPU. + */ + .data + .align 4 +intstk: + .space INTSTK /* interrupt stack */ + +GLOBAL(intr_depth) + .long -1 /* in-use marker */ + + .comm spillstk,SPILLSTK,8 + +/* + * This code gets copied to all the trap vectors + * (except ISI/DSI, ALI, the interrupts, and possibly the debugging + * traps when using IPKDB). + */ + .text + .globl _C_LABEL(trapcode),_C_LABEL(trapsize) +_C_LABEL(trapcode): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ +/* Test whether we already had PR set */ + mfsrr1 31 + mtcr 31 + bc 4,17,1f /* branch if PSL_PR is clear */ + mfsprg 31,0 + lwz 1,PC_CURPCB(31) + addi 1,1,USPACE /* stack is top of user struct */ +1: + bla s_trap +_C_LABEL(trapsize) = .-_C_LABEL(trapcode) + +/* + * For ALI: has to save DSISR and DAR + */ + .globl _C_LABEL(alitrap),_C_LABEL(alisize) +_C_LABEL(alitrap): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mfdar 30 + mfdsisr 31 + stmw 30,tempsave+16(0) + mflr 28 /* save LR */ + mfcr 29 /* save CR */ +/* Test whether we already had PR set */ + mfsrr1 31 + mtcr 31 + bc 4,17,1f /* branch if PSL_PR is clear */ + mfsprg 31,0 + lwz 1,PC_CURPCB(31) + addi 1,1,USPACE /* stack is top of user struct */ +1: + bla s_trap +_C_LABEL(alisize) = .-_C_LABEL(alitrap) + +/* + * Similar to the above for DSI + * Has to handle BAT spills + * and standard pagetable spills + */ + .globl _C_LABEL(dsitrap),_C_LABEL(dsisize) +_C_LABEL(dsitrap): + stmw 28,disisave(0) /* free r28-r31 */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + mtsprg 2,30 /* in SPRG2 */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfdar 31 /* get fault address */ + rlwinm 31,31,7,25,28 /* get segment * 8 */ + + /* get batu */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)@l(31) + mtcr 30 + bc 4,30,1f /* branch if supervisor valid is + false */ + /* get batl */ + lwz 31,_C_LABEL(battable)+4@l(31) +/* We randomly use the highest two bat registers here */ + mftb 28 + andi. 28,28,1 + bne 2f + mtdbatu 2,30 + mtdbatl 2,31 + b 3f +2: + mtdbatu 3,30 + mtdbatl 3,31 +3: + mfsprg 30,2 /* restore XER */ + mtxer 30 + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + mflr 28 /* save LR */ + bla s_dsitrap +_C_LABEL(dsisize) = .-_C_LABEL(dsitrap) + +/* + * Dedicated MPC601 version of the above. + * Considers different BAT format and combined implementation + * (being addressed as I-BAT). + */ + .globl _C_LABEL(dsitrap601),_C_LABEL(dsi601size) +_C_LABEL(dsitrap601): + stmw 28,disisave(0) /* free r28-r31 */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + mtsprg 2,30 /* in SPRG2 */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfdar 31 /* get fault address */ + rlwinm 31,31,12,20,28 /* get "segment" battable offset */ + + /* get batl */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)+4@l(31) + mtcr 30 + bc 4,25,1f /* branch if Valid is is false, + presently assumes supervisor only */ + + /* get batu */ + lwz 31,_C_LABEL(battable)@l(31) +/* We randomly use the highest two bat registers here */ + mfspr 28,SPR_RTCL_R + andi. 28,28,128 + bne 2f + mtibatu 2,31 + mtibatl 2,30 + b 3f +2: + mtibatu 3,31 + mtibatl 3,30 +3: + mfsprg 30,2 /* restore XER */ + mtxer 30 + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + mflr 28 /* save LR */ + bla s_dsitrap +_C_LABEL(dsi601size) = .-_C_LABEL(dsitrap601) + +/* + * Similar to the above for ISI + */ + .globl _C_LABEL(isitrap),_C_LABEL(isisize) +_C_LABEL(isitrap): + stmw 28,disisave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfsrr0 31 /* get fault address */ + rlwinm 31,31,7,25,28 /* get segment * 8 */ + + /* get batu */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)@l(31) + mtcr 30 + bc 4,30,1f /* branch if supervisor valid is + false */ + mtibatu 3,30 + + /* get batl */ + lwz 30,_C_LABEL(battable)+4@l(31) + mtibatl 3,30 + + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + bla s_isitrap +_C_LABEL(isisize)= .-_C_LABEL(isitrap) + +/* + * Dedicated MPC601 version of the above. + * Considers different BAT format. + */ + .globl _C_LABEL(isitrap601),_C_LABEL(isi601size) +_C_LABEL(isitrap601): + stmw 28,disisave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfsrr0 31 /* get fault address */ + rlwinm 31,31,12,20,28 /* get "segment" battable offset */ + + /* get batl */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)+4@l(31) + mtcr 30 + bc 4,25,1f /* branch if Valid is is false, + presently assumes supervisor only */ + /* get batu */ + lwz 31,_C_LABEL(battable)@l(31) + + mtibatu 3,31 + mtibatl 3,30 + + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + bla s_isitrap +_C_LABEL(isi601size)= .-_C_LABEL(isitrap601) + +/* + * This one for the external interrupt handler. + */ + .globl _C_LABEL(extint),_C_LABEL(extsize) +_C_LABEL(extint): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + lis 1,intstk+INTSTK@ha /* get interrupt stack */ + addi 1,1,intstk+INTSTK@l /* this is really intr_depth! */ + lwz 31,0(1) /* were we already running on intstk? */ + addic. 31,31,1 + stw 31,0(1) + beq 1f + mfsprg 1,1 /* yes, get old SP */ +1: + ba extintr +_C_LABEL(extsize) = .-_C_LABEL(extint) + +/* + * And this one for the decrementer interrupt handler. + */ + .globl _C_LABEL(decrint),_C_LABEL(decrsize) +_C_LABEL(decrint): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + lis 1,intstk+INTSTK@ha /* get interrupt stack */ + addi 1,1,intstk+INTSTK@l + lwz 31,0(1) /* were we already running on intstk? */ + addic. 31,31,1 + stw 31,0(1) + beq 1f + mfsprg 1,1 /* yes, get old SP */ +1: + ba decrintr +_C_LABEL(decrsize) = .-_C_LABEL(decrint) + +/* + * Now the tlb software load for 603 processors: + * (Code essentially from the 603e User Manual, Chapter 5, but + * corrected a lot.) + */ + + .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize) +_C_LABEL(tlbimiss): +#ifdef PMAPDEBUG + mfspr 2,SPR_IMISS /* exception address */ + li 1,24 /* get rid of the lower */ + srw 2,2,1 /* 24 bits */ + li 1,1 /* Load 1 */ + cmpl 2,1,1 /* is it > 16MB */ + blt 99f /* nope, skip saving these SPRs */ + li 1,0xc0 /* arbitrary */ + mfspr 2,SPR_HASH1 + stw 2,0(1) + mfspr 2,SPR_HASH2 + stw 2,4(1) + mfspr 2,SPR_IMISS + stw 2,8(1) + mfspr 2,SPR_ICMP + stw 2,12(1) +99: +#endif /* PMAPDEBUG */ + mfspr 2,SPR_HASH1 /* get first pointer */ + li 1,8 + mfctr 0 /* save counter */ + mfspr 3,SPR_ICMP /* get first compare value */ + addi 2,2,-8 /* predec pointer */ +1: + mtctr 1 /* load counter */ +2: + lwzu 1,8(2) /* get next pte */ + cmpl 0,1,3 /* see if found pte */ + bdneq 2b /* loop if not eq */ + bne 3f /* not found */ + lwz 1,4(2) /* load tlb entry lower word */ + andi. 3,1,8 /* check G-bit */ + bne 4f /* if guarded, take ISI */ + mtctr 0 /* restore counter */ + mfspr 0,SPR_IMISS /* get the miss address for the tlbli */ + mfsrr1 3 /* get the saved cr0 bits */ + mtcrf 0x80,3 /* and restore */ + ori 1,1,0x100 /* set the reference bit */ + mtspr SPR_RPA,1 /* set the pte */ + srwi 1,1,8 /* get byte 7 of pte */ + tlbli 0 /* load the itlb */ + stb 1,6(2) /* update page table */ + rfi + +3: /* not found in pteg */ + andi. 1,3,0x40 /* have we already done second hash? */ + bne 5f + mfspr 2,SPR_HASH2 /* get the second pointer */ + ori 3,3,0x40 /* change the compare value */ + li 1,8 + addi 2,2,-8 /* predec pointer */ + b 1b +4: /* guarded */ + mfsrr1 3 + andi. 2,3,0xffff /* clean upper srr1 */ + oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ + b 6f +5: /* not found anywhere */ + mfsrr1 3 + andi. 2,3,0xffff /* clean upper srr1 */ + oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ +6: + mtctr 0 /* restore counter */ + mtsrr1 2 + mfmsr 0 + xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,3 /* restore cr0 */ + mtmsr 0 /* now with native gprs */ + isync + ba EXC_ISI +_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss) + + .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize) +_C_LABEL(tlbdlmiss): + mfspr 2,SPR_HASH1 /* get first pointer */ + li 1,8 + mfctr 0 /* save counter */ + mfspr 3,SPR_DCMP /* get first compare value */ + addi 2,2,-8 /* predec pointer */ +1: + mtctr 1 /* load counter */ +2: + lwzu 1,8(2) /* get next pte */ + cmpl 0,1,3 /* see if found pte */ + bdneq 2b /* loop if not eq */ + bne 3f /* not found */ + lwz 1,4(2) /* load tlb entry lower word */ + mtctr 0 /* restore counter */ + mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ + mfsrr1 3 /* get the saved cr0 bits */ + mtcrf 0x80,3 /* and restore */ + ori 1,1,0x100 /* set the reference bit */ + mtspr SPR_RPA,1 /* set the pte */ + srwi 1,1,8 /* get byte 7 of pte */ + tlbld 0 /* load the dtlb */ + stb 1,6(2) /* update page table */ + rfi + +3: /* not found in pteg */ + andi. 1,3,0x40 /* have we already done second hash? */ + bne 5f + mfspr 2,SPR_HASH2 /* get the second pointer */ + ori 3,3,0x40 /* change the compare value */ + li 1,8 + addi 2,2,-8 /* predec pointer */ + b 1b +5: /* not found anywhere */ + mfsrr1 3 + lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ + mtctr 0 /* restore counter */ + andi. 2,3,0xffff /* clean upper srr1 */ + mtsrr1 2 + mtdsisr 1 /* load the dsisr */ + mfspr 1,SPR_DMISS /* get the miss address */ + mtdar 1 /* put in dar */ + mfmsr 0 + xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,3 /* restore cr0 */ + mtmsr 0 /* now with native gprs */ + isync + ba EXC_DSI +_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss) + + .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize) +_C_LABEL(tlbdsmiss): + mfspr 2,SPR_HASH1 /* get first pointer */ + li 1,8 + mfctr 0 /* save counter */ + mfspr 3,SPR_DCMP /* get first compare value */ + addi 2,2,-8 /* predec pointer */ +1: + mtctr 1 /* load counter */ +2: + lwzu 1,8(2) /* get next pte */ + cmpl 0,1,3 /* see if found pte */ + bdneq 2b /* loop if not eq */ + bne 3f /* not found */ + lwz 1,4(2) /* load tlb entry lower word */ + andi. 3,1,0x80 /* check the C-bit */ + beq 4f +5: + mtctr 0 /* restore counter */ + mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ + mfsrr1 3 /* get the saved cr0 bits */ + mtcrf 0x80,3 /* and restore */ + mtspr SPR_RPA,1 /* set the pte */ + tlbld 0 /* load the dtlb */ + rfi + +3: /* not found in pteg */ + andi. 1,3,0x40 /* have we already done second hash? */ + bne 5f + mfspr 2,SPR_HASH2 /* get the second pointer */ + ori 3,3,0x40 /* change the compare value */ + li 1,8 + addi 2,2,-8 /* predec pointer */ + b 1b +4: /* found, but C-bit = 0 */ + rlwinm. 3,1,30,0,1 /* test PP */ + bge- 7f + andi. 3,1,1 + beq+ 8f +9: /* found, but protection violation (PP==00)*/ + mfsrr1 3 + lis 1,0xa000000@h /* indicate protection violation + on store */ + b 1f +7: /* found, PP=1x */ + mfspr 3,SPR_DMISS /* get the miss address */ + mfsrin 1,3 /* get the segment register */ + mfsrr1 3 + rlwinm 3,3,18,31,31 /* get PR-bit */ + rlwnm. 2,2,3,1,1 /* get the key */ + bne- 9b /* protection violation */ +8: /* found, set reference/change bits */ + lwz 1,4(2) /* reload tlb entry */ + ori 1,1,0x180 + sth 1,6(2) + b 5b +5: /* not found anywhere */ + mfsrr1 3 + lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ + /* dsisr<6> to flag store */ +1: + mtctr 0 /* restore counter */ + andi. 2,3,0xffff /* clean upper srr1 */ + mtsrr1 2 + mtdsisr 1 /* load the dsisr */ + mfspr 1,SPR_DMISS /* get the miss address */ + mtdar 1 /* put in dar */ + mfmsr 0 + xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,3 /* restore cr0 */ + mtmsr 0 /* now with native gprs */ + isync + ba EXC_DSI +_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss) + +#if defined(DDB) || defined(KGDB) +#define ddbsave 0xde0 /* primary save area for DDB */ +/* + * In case of DDB we want a separate trap catcher for it + */ + .local ddbstk + .comm ddbstk,INTSTK,8 /* ddb stack */ + + .globl _C_LABEL(ddblow),_C_LABEL(ddbsize) +_C_LABEL(ddblow): + mtsprg 1,1 /* save SP */ + stmw 28,ddbsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + lis 1,ddbstk+INTSTK@ha /* get new SP */ + addi 1,1,ddbstk+INTSTK@l + bla ddbtrap +_C_LABEL(ddbsize) = .-_C_LABEL(ddblow) +#endif /* DDB | KGDB */ + +#ifdef IPKDB +#define ipkdbsave 0xde0 /* primary save area for IPKDB */ +/* + * In case of IPKDB we want a separate trap catcher for it + */ + + .local ipkdbstk + .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ + + .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize) +_C_LABEL(ipkdblow): + mtsprg 1,1 /* save SP */ + stmw 28,ipkdbsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + lis 1,ipkdbstk+INTSTK@ha /* get new SP */ + addi 1,1,ipkdbstk+INTSTK@l + bla ipkdbtrap +_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow) +#endif /* IPKDB */ + +/* + * FRAME_SETUP assumes: + * SPRG1 SP (1) + * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) + * 28 LR + * 29 CR + * 1 kernel stack + * LR trap type + * SRR0/1 as at start of trap + */ +#define FRAME_SETUP(savearea) \ +/* Have to enable translation to allow access of kernel stack: */ \ + mfsrr0 30; \ + mfsrr1 31; \ + stmw 30,savearea+24(0); \ + mfmsr 30; \ + ori 30,30,(PSL_DR|PSL_IR); \ + mtmsr 30; \ + isync; \ + mfsprg 31,1; \ + stwu 31,-FRAMELEN(1); \ + stw 0,FRAME_0+8(1); \ + stw 31,FRAME_1+8(1); \ + stw 28,FRAME_LR+8(1); \ + stw 29,FRAME_CR+8(1); \ + lmw 28,savearea(0); \ + stmw 2,FRAME_2+8(1); \ + lmw 28,savearea+16(0); \ + mfxer 3; \ + mfctr 4; \ + mflr 5; \ + andi. 5,5,0xff00; \ + stw 3,FRAME_XER+8(1); \ + stw 4,FRAME_CTR+8(1); \ + stw 5,FRAME_EXC+8(1); \ + stw 28,FRAME_DAR+8(1); \ + stw 29,FRAME_DSISR+8(1); \ + stw 30,FRAME_SRR0+8(1); \ + stw 31,FRAME_SRR1+8(1) + +#define FRAME_LEAVE(savearea) \ +/* Now restore regs: */ \ + lwz 2,FRAME_SRR0+8(1); \ + lwz 3,FRAME_SRR1+8(1); \ + lwz 4,FRAME_CTR+8(1); \ + lwz 5,FRAME_XER+8(1); \ + lwz 6,FRAME_LR+8(1); \ + lwz 7,FRAME_CR+8(1); \ + stw 2,savearea(0); \ + stw 3,savearea+4(0); \ + mtctr 4; \ + mtxer 5; \ + mtlr 6; \ + mtsprg 1,7; /* save cr */ \ + lmw 2,FRAME_2+8(1); \ + lwz 0,FRAME_0+8(1); \ + lwz 1,FRAME_1+8(1); \ + mtsprg 2,2; /* save r2 & r3 */ \ + mtsprg 3,3; \ +/* Disable translation, machine check and recoverability: */ \ + mfmsr 2; \ + andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ + mtmsr 2; \ + isync; \ +/* Decide whether we return to user mode: */ \ + lwz 3,savearea+4(0); \ + mtcr 3; \ + bc 4,17,1f; /* branch if PSL_PR is false */ \ +/* Restore user & kernel access SR: */ \ + mfsprg 2,0; \ + lwz 2,PC_CURPMAP(2); \ + lwz 3,PM_SR+0(2); \ + mtsr 0,3; /* restore SR0 */ \ + lwz 3,PM_SR+4(2); \ + mtsr 1,3; /* restore SR1 */ \ + lwz 3,PM_SR+8(2); \ + mtsr 2,3; /* restore SR2 */ \ + lwz 3,PM_SR+12(2); \ + mtsr 3,3; /* restore SR3 */ \ + lwz 3,PM_SR+16(2); \ + mtsr 4,3; /* restore SR4 */ \ + lwz 3,PM_SR+20(2); \ + mtsr 5,3; /* restore SR5 */ \ + lwz 3,PM_SR+24(2); \ + mtsr 6,3; /* restore SR6 */ \ + lwz 3,PM_SR+28(2); \ + mtsr 7,3; /* restore SR7 */ \ + lwz 3,PM_USRSR(2); \ + mtsr USER_SR,3; \ + lwz 3,PM_KERNELSR(2); \ + mtsr KERNEL_SR,3; \ +1: mfsprg 2,1; /* restore cr */ \ + mtcr 2; \ + lwz 2,savearea(0); \ + lwz 3,savearea+4(0); \ + mtsrr0 2; \ + mtsrr1 3; \ + mfsprg 2,2; /* restore r2 & r3 */ \ + mfsprg 3,3 + +/* + * Preamble code for DSI/ISI traps + */ +disitrap: + lmw 30,disisave(0) + stmw 30,tempsave(0) + lmw 30,disisave+8(0) + stmw 30,tempsave+8(0) + mfdar 30 + mfdsisr 31 + stmw 30,tempsave+16(0) +realtrap: +/* Test whether we already had PR set */ + mfsrr1 1 + mtcr 1 + mfsprg 1,1 /* restore SP (might have been + overwritten) */ + bc 4,17,s_trap /* branch if PSL_PR is false */ + mfsprg 31,0 + lwz 1,PC_CURPCB(31) + addi 1,1,USPACE /* stack is top of user struct */ + +/* + * Now the common trap catching code. + */ +s_trap: +/* First have to enable KERNEL mapping */ + lis 31,KERNEL_SEGMENT@h + ori 31,31,KERNEL_SEGMENT@l + mtsr KERNEL_SR,31 +/* Obliterate SRs so BAT spills work correctly */ + lis 31,EMPTY_SEGMENT@h + ori 31,31,EMPTY_SEGMENT@l + mtsr 0,31 + mtsr 1,31 + mtsr 2,31 + mtsr 3,31 + mtsr 4,31 + mtsr 5,31 + mtsr 6,31 + mtsr 7,31 + FRAME_SETUP(tempsave) +/* Now we can recover interrupts again: */ + mfmsr 7 + ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l + mtmsr 7 + isync +/* Call C trap code: */ +trapagain: + addi 3,1,8 + bl _C_LABEL(trap) + .globl _C_LABEL(trapexit) +_C_LABEL(trapexit): +/* Disable interrupts: */ + mfmsr 3 + andi. 3,3,~PSL_EE@l + mtmsr 3 +/* Test AST pending: */ + lwz 5,FRAME_SRR1+8(1) + mtcr 5 + bc 4,17,1f /* branch if PSL_PR is false */ + lis 3,_C_LABEL(astpending)@ha + lwz 4,_C_LABEL(astpending)@l(3) + andi. 4,4,1 + beq 1f + li 6,EXC_AST + stw 6,FRAME_EXC+8(1) + b trapagain +1: + FRAME_LEAVE(tempsave) + rfi + +/* + * DSI second stage fault handler + */ +s_dsitrap: + mfdsisr 31 /* test whether this may be a + spill fault */ + mtcr 31 + mtsprg 1,1 /* save SP */ + bc 4,1,disitrap /* branch if table miss is false */ + lis 1,spillstk+SPILLSTK@ha + addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ + stwu 1,-SPFRAMELEN(1) + stw 0,SPFRAME_R0(1) /* save non-volatile registers */ + stw 3,SPFRAME_R3(1) + stw 4,SPFRAME_R4(1) + stw 5,SPFRAME_R5(1) + stw 6,SPFRAME_R6(1) + stw 7,SPFRAME_R7(1) + stw 8,SPFRAME_R8(1) + stw 9,SPFRAME_R9(1) + stw 10,SPFRAME_R10(1) + stw 11,SPFRAME_R11(1) + stw 12,SPFRAME_R12(1) + mflr 30 /* save trap type */ + mfctr 31 /* & CTR */ + mfdar 3 +s_pte_spill: + bl _C_LABEL(pmap_pte_spill) /* try a spill */ + or. 3,3,3 + mtctr 31 /* restore CTR */ + mtlr 30 /* and trap type */ + mfsprg 31,2 /* get saved XER */ + mtxer 31 /* restore XER */ + lwz 12,SPFRAME_R12(1) /* restore non-volatile registers */ + lwz 11,SPFRAME_R11(1) + lwz 10,SPFRAME_R10(1) + lwz 9,SPFRAME_R9(1) + lwz 8,SPFRAME_R8(1) + lwz 7,SPFRAME_R7(1) + lwz 6,SPFRAME_R6(1) + lwz 5,SPFRAME_R5(1) + lwz 4,SPFRAME_R4(1) + lwz 3,SPFRAME_R3(1) + lwz 0,SPFRAME_R0(1) + beq disitrap + mfsprg 1,1 /* restore SP */ + mtcr 29 /* restore CR */ + mtlr 28 /* restore LR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ + +/* + * ISI second stage fault handler + */ +s_isitrap: + mfsrr1 31 /* test whether this may be a + spill fault */ + mtcr 31 + mtsprg 1,1 /* save SP */ + bc 4,1,disitrap /* branch if table miss is false */ + lis 1,spillstk+SPILLSTK@ha + addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ + stwu 1,-SPFRAMELEN(1) + stw 0,SPFRAME_R0(1) /* save non-volatile registers */ + stw 3,SPFRAME_R3(1) + stw 4,SPFRAME_R4(1) + stw 5,SPFRAME_R5(1) + stw 6,SPFRAME_R6(1) + stw 7,SPFRAME_R7(1) + stw 8,SPFRAME_R8(1) + stw 9,SPFRAME_R9(1) + stw 10,SPFRAME_R10(1) + stw 11,SPFRAME_R11(1) + stw 12,SPFRAME_R12(1) + mfxer 30 /* save XER */ + mtsprg 2,30 + mflr 30 /* save trap type */ + mfctr 31 /* & ctr */ + mfsrr0 3 + b s_pte_spill /* above */ + +/* + * External interrupt second level handler + */ +#define INTRENTER \ +/* Save non-volatile registers: */ \ + stwu 1,-IFRAMELEN(1); /* temporarily */ \ + stw 0,IFRAME_R0(1); \ + mfsprg 0,1; /* get original SP */ \ + stw 0,IFRAME_R1(1); /* and store it */ \ + stw 3,IFRAME_R3(1); \ + stw 4,IFRAME_R4(1); \ + stw 5,IFRAME_R5(1); \ + stw 6,IFRAME_R6(1); \ + stw 7,IFRAME_R7(1); \ + stw 8,IFRAME_R8(1); \ + stw 9,IFRAME_R9(1); \ + stw 10,IFRAME_R10(1); \ + stw 11,IFRAME_R11(1); \ + stw 12,IFRAME_R12(1); \ + stw 28,IFRAME_LR(1); /* saved LR */ \ + stw 29,IFRAME_CR(1); /* saved CR */ \ + stw 30,IFRAME_XER(1); /* saved XER */ \ + lmw 28,tempsave(0); /* restore r28-r31 */ \ + mfctr 6; \ + lis 5,_C_LABEL(intr_depth)@ha; \ + lwz 5,_C_LABEL(intr_depth)@l(5); \ + mfsrr0 4; \ + mfsrr1 3; \ + stw 6,IFRAME_CTR(1); \ + stw 5,IFRAME_INTR_DEPTH(1); \ + stw 4,IFRAME_SRR0(1); \ + stw 3,IFRAME_SRR1(1); \ + mtcr 3; \ + bc 4,17,99f; /* branch if PSL_PR is false */ \ + lis 3,EMPTY_SEGMENT@h; \ + ori 3,3,EMPTY_SEGMENT@l; \ + mtsr 0,3; /* reset SRs so BAT spills work */ \ + mtsr 1,3; \ + mtsr 2,3; \ + mtsr 3,3; \ + mtsr 4,3; \ + mtsr 5,3; \ + mtsr 6,3; \ + mtsr 7,3; \ +/* interrupts are recoverable here, and enable translation */ \ + lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ + ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ + mtsr KERNEL_SR,3; \ +99: mfmsr 5; \ + ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ + mtmsr 5; \ + isync + + .globl _C_LABEL(extint_call) +extintr: + INTRENTER +_C_LABEL(extint_call): + bl _C_LABEL(extint_call) /* to be filled in later */ + +intr_exit: +/* Disable interrupts (should already be disabled) and MMU here: */ + mfmsr 3 + andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l + mtmsr 3 + isync +/* restore possibly overwritten registers: */ + lwz 12,IFRAME_R12(1) + lwz 11,IFRAME_R11(1) + lwz 10,IFRAME_R10(1) + lwz 9,IFRAME_R9(1) + lwz 8,IFRAME_R8(1) + lwz 7,IFRAME_R7(1) + lwz 6,IFRAME_SRR1(1) + lwz 5,IFRAME_SRR0(1) + lwz 4,IFRAME_CTR(1) + lwz 3,IFRAME_XER(1) + mtsrr1 6 + mtsrr0 5 + mtctr 4 + mtxer 3 +/* Returning to user mode? */ + mtcr 6 /* saved SRR1 */ + bc 4,17,1f /* branch if PSL_PR is false */ + mfsprg 31,0 + lwz 3,PC_CURPMAP(31) + lwz 4,PM_SR+0(3) + mtsr 0,4 /* Restore SR0 */ + lwz 4,PM_SR+4(3) + mtsr 1,4 /* Restore SR1 */ + lwz 4,PM_SR+8(3) + mtsr 2,4 /* Restore SR2 */ + lwz 4,PM_SR+12(3) + mtsr 3,4 /* Restore SR3 */ + lwz 4,PM_SR+16(3) + mtsr 4,4 /* Restore SR4 */ + lwz 4,PM_SR+20(3) + mtsr 5,4 /* Restore SR5 */ + lwz 4,PM_SR+24(3) + mtsr 6,4 /* Restore SR6 */ + lwz 4,PM_SR+28(3) + mtsr 7,4 /* Restore SR7 */ + lwz 3,PM_KERNELSR(3) + mtsr KERNEL_SR,3 /* Restore kernel SR */ + lis 3,_C_LABEL(astpending)@ha /* Test AST pending */ + lwz 4,_C_LABEL(astpending)@l(3) + andi. 4,4,1 + beq 1f +/* Setup for entry to realtrap: */ + lwz 3,IFRAME_R1(1) /* get saved SP */ + mtsprg 1,3 + li 6,EXC_AST + stmw 28,tempsave(0) /* establish tempsave again */ + mtlr 6 + lwz 28,IFRAME_LR(1) /* saved LR */ + lwz 29,IFRAME_CR(1) /* saved CR */ + lwz 6,IFRAME_R6(1) + lwz 5,IFRAME_R5(1) + lwz 4,IFRAME_R4(1) + lwz 3,IFRAME_R3(1) + lwz 0,IFRAME_R0(1) + lis 30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ + lwz 31,_C_LABEL(intr_depth)@l(30) + addi 31,31,-1 + stw 31,_C_LABEL(intr_depth)@l(30) + b realtrap +1: +/* Here is the normal exit of extintr: */ + lwz 5,IFRAME_CR(1) + lwz 6,IFRAME_LR(1) + mtcr 5 + mtlr 6 + lwz 6,IFRAME_R6(1) + lwz 5,IFRAME_R5(1) + lis 3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ + lwz 4,_C_LABEL(intr_depth)@l(3) + addi 4,4,-1 + stw 4,_C_LABEL(intr_depth)@l(3) + lwz 4,IFRAME_R4(1) + lwz 3,IFRAME_R3(1) + lwz 0,IFRAME_R0(1) + lwz 1,IFRAME_R1(1) + rfi + +/* + * Decrementer interrupt second level handler + */ +decrintr: + INTRENTER + addi 3,1,8 /* intr frame -> clock frame */ + bl _C_LABEL(decr_intr) + b intr_exit + +#if defined(DDB) +/* + * Deliberate entry to ddbtrap + */ + .globl _C_LABEL(ddb_trap) +_C_LABEL(ddb_trap): + mtsprg 1,1 + mfmsr 3 + mtsrr1 3 + andi. 3,3,~(PSL_EE|PSL_ME)@l + mtmsr 3 /* disable interrupts */ + isync + stmw 28,ddbsave(0) + mflr 28 + li 29,EXC_BPT + mtlr 29 + mfcr 29 + mtsrr0 28 +#endif /* DDB */ + +#if defined(DDB) || defined(KGDB) +/* + * Now the ddb trap catching code. + */ +ddbtrap: + FRAME_SETUP(ddbsave) +/* Call C trap code: */ + addi 3,1,8 + bl _C_LABEL(ddb_trap_glue) + or. 3,3,3 + bne ddbleave +/* This wasn't for DDB, so switch to real trap: */ + lwz 3,FRAME_EXC+8(1) /* save exception */ + stw 3,ddbsave+8(0) + FRAME_LEAVE(ddbsave) + mtsprg 1,1 /* prepare for entrance to realtrap */ + stmw 28,tempsave(0) + mflr 28 + mfcr 29 + lwz 31,ddbsave+8(0) + mtlr 31 + b realtrap +ddbleave: + FRAME_LEAVE(ddbsave) + rfi +#endif /* DDB || KGDB */ + +#ifdef IPKDB +/* + * Deliberate entry to ipkdbtrap + */ + .globl _C_LABEL(ipkdb_trap) +_C_LABEL(ipkdb_trap): + mtsprg 1,1 + mfmsr 3 + mtsrr1 3 + andi. 3,3,~(PSL_EE|PSL_ME)@l + mtmsr 3 /* disable interrupts */ + isync + stmw 28,ipkdbsave(0) + mflr 28 + li 29,EXC_BPT + mtlr 29 + mfcr 29 + mtsrr0 28 + +/* + * Now the ipkdb trap catching code. + */ +ipkdbtrap: + FRAME_SETUP(ipkdbsave) +/* Call C trap code: */ + addi 3,1,8 + bl _C_LABEL(ipkdb_trap_glue) + or. 3,3,3 + bne ipkdbleave +/* This wasn't for IPKDB, so switch to real trap: */ + lwz 3,FRAME_EXC+8(1) /* save exception */ + stw 3,ipkdbsave+8(0) + FRAME_LEAVE(ipkdbsave) + mtsprg 1,1 /* prepare for entrance to realtrap */ + stmw 28,tempsave(0) + mflr 28 + mfcr 29 + lwz 31,ipkdbsave+8(0) + mtlr 31 + b realtrap +ipkdbleave: + FRAME_LEAVE(ipkdbsave) + rfi + +ipkdbfault: + ba _ipkdbfault +_ipkdbfault: + mfsrr0 3 + addi 3,3,4 + mtsrr0 3 + li 3,-1 + rfi + +/* + * int ipkdbfbyte(unsigned char *p) + */ + .globl _C_LABEL(ipkdbfbyte) +_C_LABEL(ipkdbfbyte): + li 9,EXC_DSI /* establish new fault routine */ + lwz 5,0(9) + lis 6,ipkdbfault@ha + lwz 6,ipkdbfault@l(6) + stw 6,0(9) +#ifdef IPKDBUSERHACK + lis 8,_C_LABEL(ipkdbsr)@ha + lwz 8,_C_LABEL(ipkdbsr)@l(8) + mtsr USER_SR,8 + isync +#endif + dcbst 0,9 /* flush data... */ + sync + icbi 0,9 /* and instruction caches */ + lbz 3,0(3) /* fetch data */ + stw 5,0(9) /* restore previous fault handler */ + dcbst 0,9 /* and flush data... */ + sync + icbi 0,9 /* and instruction caches */ + blr + +/* + * int ipkdbsbyte(unsigned char *p, int c) + */ + .globl _C_LABEL(ipkdbsbyte) +_C_LABEL(ipkdbsbyte): + li 9,EXC_DSI /* establish new fault routine */ + lwz 5,0(9) + lis 6,ipkdbfault@ha + lwz 6,ipkdbfault@l(6) + stw 6,0(9) +#ifdef IPKDBUSERHACK + lis 8,_C_LABEL(ipkdbsr)@ha + lwz 8,_C_LABEL(ipkdbsr)@l(8) + mtsr USER_SR,8 + isync +#endif + dcbst 0,9 /* flush data... */ + sync + icbi 0,9 /* and instruction caches */ + mr 6,3 + xor 3,3,3 + stb 4,0(6) + dcbst 0,6 /* Now do appropriate flushes + to data... */ + sync + icbi 0,6 /* and instruction caches */ + stw 5,0(9) /* restore previous fault handler */ + dcbst 0,9 /* and flush data... */ + sync + icbi 0,9 /* and instruction caches */ + blr +#endif /* IPKDB */ diff --git a/sys/powerpc/include/frame.h b/sys/powerpc/include/frame.h index 72dbd9f..63f07bf 100644 --- a/sys/powerpc/include/frame.h +++ b/sys/powerpc/include/frame.h @@ -90,4 +90,50 @@ struct callframe { register_t cf_arg1; }; +#define IFRAMELEN sizeof(struct intrframe) +struct intrframe { + register_t r1; /* 0 */ + register_t _pad4; /* 4 */ + /* + * The next 4 fields are "clockframe" + */ + register_t srr1; /* 8 */ + register_t srr0; /* 12 */ + int pri; /* 16 */ + int intr_depth; /* 20 */ + register_t vrsave; /* 24 */ + register_t ctr; /* 28 */ + register_t xer; /* 32 */ + register_t cr; /* 36 */ + register_t lr; /* 40 */ + register_t r12; /* 44 */ + register_t r11; /* 48 */ + register_t r10; /* 52 */ + register_t r9; /* 56 */ + register_t r8; /* 60 */ + register_t r7; /* 64 */ + register_t r6; /* 68 */ + register_t r5; /* 72 */ + register_t r4; /* 76 */ + register_t r3; /* 80 */ + register_t r0; /* 84 */ +}; + +#define SPFRAMELEN sizeof(struct spillframe) +struct spillframe { + register_t r1; /* 0 */ + register_t _pad4; /* 4 */ + register_t r12; /* 8 */ + register_t r11; /* 12 */ + register_t r10; /* 16 */ + register_t r9; /* 20 */ + register_t r8; /* 24 */ + register_t r7; /* 28 */ + register_t r6; /* 32 */ + register_t r5; /* 36 */ + register_t r4; /* 40 */ + register_t r3; /* 44 */ + register_t r0; /* 48 */ +}; + #endif /* _MACHINE_FRAME_H_ */ diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h index 4d37de4..c222ee0 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -33,10 +33,13 @@ #ifdef _KERNEL #include <machine/cpufunc.h> +struct pmap; + #define PCPU_MD_FIELDS \ int pc_inside_intr; \ u_int32_t pc_next_asn; /* next ASN to alloc */ \ - u_int32_t pc_current_asngen /* ASN rollover check */ + u_int32_t pc_current_asngen; /* ASN rollover check */\ + struct pmap *pc_curpmap /* current pmap */ #define PCPUP ((struct pcpu *) powerpc_get_pcpup()) diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h new file mode 100644 index 0000000..d485fb2 --- /dev/null +++ b/sys/powerpc/include/spr.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _POWERPC_SPR_H_ +#define _POWERPC_SPR_H_ + +#ifndef _LOCORE +#define mtspr(reg, val) \ + __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val)) +#define mfspr(reg) \ + ( { u_int32_t val; \ + __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \ + val; } ) +#endif /* _LOCORE */ + +/* + * Special Purpose Register declarations. + * + * The first column in the comments indicates which PowerPC + * architectures the SPR is valid on - 4 for 4xx series, + * 6 for 6xx/7xx series and 8 for 8xx and 8xxx series. + */ + +#define SPR_MQ 0x000 /* .6. 601 MQ register */ +#define SPR_XER 0x001 /* 468 Fixed Point Exception Register */ +#define SPR_RTCU_R 0x004 /* .6. 601 RTC Upper - Read */ +#define SPR_RTCL_R 0x005 /* .6. 601 RTC Lower - Read */ +#define SPR_LR 0x008 /* 468 Link Register */ +#define SPR_CTR 0x009 /* 468 Count Register */ +#define SPR_DSISR 0x012 /* .68 DSI exception source */ +#define DSISR_DIRECT 0x80000000 /* Direct-store error exception */ +#define DSISR_NOTFOUND 0x40000000 /* Translation not found */ +#define DSISR_PROTECT 0x08000000 /* Memory access not permitted */ +#define DSISR_INVRX 0x04000000 /* Reserve-indexed insn direct-store access */ +#define DSISR_STORE 0x02000000 /* Store operation */ +#define DSISR_DABR 0x00400000 /* DABR match */ +#define DSISR_SEGMENT 0x00200000 /* XXX; not in 6xx PEM */ +#define DSISR_EAR 0x00100000 /* eciwx/ecowx && EAR[E] == 0 */ +#define SPR_DAR 0x013 /* .68 Data Address Register */ +#define SPR_RTCU_W 0x014 /* .6. 601 RTC Upper - Write */ +#define SPR_RTCL_W 0x015 /* .6. 601 RTC Lower - Write */ +#define SPR_DEC 0x016 /* .68 DECrementer register */ +#define SPR_SDR1 0x019 /* .68 Page table base address register */ +#define SPR_SRR0 0x01a /* 468 Save/Restore Register 0 */ +#define SPR_SRR1 0x01b /* 468 Save/Restore Register 1 */ +#define SPR_USPRG0 0x100 /* 4.. User SPR General 0 */ +#define SPR_SPRG0 0x110 /* 468 SPR General 0 */ +#define SPR_SPRG1 0x111 /* 468 SPR General 1 */ +#define SPR_SPRG2 0x112 /* 468 SPR General 2 */ +#define SPR_SPRG3 0x113 /* 468 SPR General 3 */ +#define SPR_SPRG4 0x114 /* 4.. SPR General 4 */ +#define SPR_SPRG5 0x115 /* 4.. SPR General 5 */ +#define SPR_SPRG6 0x116 /* 4.. SPR General 6 */ +#define SPR_SPRG7 0x117 /* 4.. SPR General 7 */ +#define SPR_EAR 0x11a /* .68 External Access Register */ +#define SPR_TBL 0x11c /* 468 Time Base Lower */ +#define SPR_TBU 0x11d /* 468 Time Base Upper */ +#define SPR_PVR 0x11f /* 468 Processor Version Register */ +#define MPC601 0x0001 +#define MPC603 0x0003 +#define MPC604 0x0004 +#define MPC602 0x0005 +#define MPC603e 0x0006 +#define MPC603ev 0x0007 +#define MPC750 0x0008 +#define MPC604ev 0x0009 +#define MPC7400 0x000c +#define MPC620 0x0014 +#define MPC860 0x0050 +#define MPC8240 0x0081 +#define MPC7450 0x8000 +#define MPC7455 0x8001 +#define MPC7410 0x800c +#define IBM405GP 0x4011 +#define IBM405L 0x4161 +#define SPR_IBAT0U 0x210 /* .68 Instruction BAT Reg 0 Upper */ +#define SPR_IBAT0L 0x211 /* .68 Instruction BAT Reg 0 Lower */ +#define SPR_IBAT1U 0x212 /* .68 Instruction BAT Reg 1 Upper */ +#define SPR_IBAT1L 0x213 /* .68 Instruction BAT Reg 1 Lower */ +#define SPR_IBAT2U 0x214 /* .68 Instruction BAT Reg 2 Upper */ +#define SPR_IBAT2L 0x215 /* .68 Instruction BAT Reg 2 Lower */ +#define SPR_IBAT3U 0x216 /* .68 Instruction BAT Reg 3 Upper */ +#define SPR_IBAT3L 0x217 /* .68 Instruction BAT Reg 3 Lower */ +#define SPR_DBAT0U 0x218 /* .68 Data BAT Reg 0 Upper */ +#define SPR_DBAT0L 0x219 /* .68 Data BAT Reg 0 Lower */ +#define SPR_DBAT1U 0x21a /* .68 Data BAT Reg 1 Upper */ +#define SPR_DBAT1L 0x21b /* .68 Data BAT Reg 1 Lower */ +#define SPR_DBAT2U 0x21c /* .68 Data BAT Reg 2 Upper */ +#define SPR_DBAT2L 0x21d /* .68 Data BAT Reg 2 Lower */ +#define SPR_DBAT3U 0x21e /* .68 Data BAT Reg 3 Upper */ +#define SPR_DBAT3L 0x21f /* .68 Data BAT Reg 3 Lower */ +#define SPI_IBAT4U 0x230 /* .6. Instruction BAT Reg 4 Upper */ +#define SPI_IBAT4L 0x231 /* .6. Instruction BAT Reg 4 Lower */ +#define SPI_IBAT5U 0x232 /* .6. Instruction BAT Reg 5 Upper */ +#define SPI_IBAT5L 0x233 /* .6. Instruction BAT Reg 5 Lower */ +#define SPI_IBAT6U 0x234 /* .6. Instruction BAT Reg 6 Upper */ +#define SPI_IBAT6L 0x235 /* .6. Instruction BAT Reg 6 Lower */ +#define SPI_IBAT7U 0x236 /* .6. Instruction BAT Reg 7 Upper */ +#define SPI_IBAT7L 0x237 /* .6. Instruction BAT Reg 7 Lower */ +#define SPI_DBAT4U 0x238 /* .6. Data BAT Reg 4 Upper */ +#define SPI_DBAT4L 0x239 /* .6. Data BAT Reg 4 Lower */ +#define SPI_DBAT5U 0x23a /* .6. Data BAT Reg 5 Upper */ +#define SPI_DBAT5L 0x23b /* .6. Data BAT Reg 5 Lower */ +#define SPI_DBAT6U 0x23c /* .6. Data BAT Reg 6 Upper */ +#define SPI_DBAT6L 0x23d /* .6. Data BAT Reg 6 Lower */ +#define SPI_DBAT7U 0x23e /* .6. Data BAT Reg 7 Upper */ +#define SPI_DBAT7L 0x23f /* .6. Data BAT Reg 7 Lower */ +#define SPR_UMMCR2 0x3a0 /* .6. User Monitor Mode Control Register 2 */ +#define SPR_UMMCR0 0x3a8 /* .6. User Monitor Mode Control Register 0 */ +#define SPR_USIA 0x3ab /* .6. User Sampled Instruction Address */ +#define SPR_UMMCR1 0x3ac /* .6. User Monitor Mode Control Register 1 */ +#define SPR_ZPR 0x3b0 /* 4.. Zone Protection Register */ +#define SPR_MMCR2 0x3b0 /* .6. Monitor Mode Control Register 2 */ +#define SPR_MMCR2_THRESHMULT_32 0x80000000 /* Multiply MMCR0 threshold by 32 */ +#define SPR_MMCR2_THRESHMULT_2 0x00000000 /* Multiply MMCR0 threshold by 2 */ +#define SPR_PID 0x3b1 /* 4.. Process ID */ +#define SPR_PMC5 0x3b1 /* .6. Performance Counter Register 5 */ +#define SPR_PMC6 0x3b2 /* .6. Performance Counter Register 6 */ +#define SPR_CCR0 0x3b3 /* 4.. Core Configuration Register 0 */ +#define SPR_IAC3 0x3b4 /* 4.. Instruction Address Compare 3 */ +#define SPR_IAC4 0x3b5 /* 4.. Instruction Address Compare 4 */ +#define SPR_DVC1 0x3b6 /* 4.. Data Value Compare 1 */ +#define SPR_DVC2 0x3b7 /* 4.. Data Value Compare 2 */ +#define SPR_MMCR0 0x3b8 /* .6. Monitor Mode Control Register 0 */ +#define SPR_MMCR0_FC 0x80000000 /* Freeze counters */ +#define SPR_MMCR0_FCS 0x40000000 /* Freeze counters in supervisor mode */ +#define SPR_MMCR0_FCP 0x20000000 /* Freeze counters in user mode */ +#define SPR_MMCR0_FCM1 0x10000000 /* Freeze counters when mark=1 */ +#define SPR_MMCR0_FCM0 0x08000000 /* Freeze counters when mark=0 */ +#define SPR_MMCR0_PMXE 0x04000000 /* Enable PM interrupt */ +#define SPR_MMCR0_FCECE 0x02000000 /* Freeze counters after event */ +#define SPR_MMCR0_TBSEL_15 0x01800000 /* Count bit 15 of TBL */ +#define SPR_MMCR0_TBSEL_19 0x01000000 /* Count bit 19 of TBL */ +#define SPR_MMCR0_TBSEL_23 0x00800000 /* Count bit 23 of TBL */ +#define SPR_MMCR0_TBSEL_31 0x00000000 /* Count bit 31 of TBL */ +#define SPR_MMCR0_TBEE 0x00400000 /* Time-base event enable */ +#define SPR_MMCRO_THRESHOLD(x) ((x) << 16) /* Threshold value */ +#define SPR_MMCR0_PMC1CE 0x00008000 /* PMC1 condition enable */ +#define SPR_MMCR0_PMCNCE 0x00004000 /* PMCn condition enable */ +#define SPR_MMCR0_TRIGGER 0x00002000 /* Trigger */ +#define SPR_MMCR0_PMC1SEL(x) ((x) << 6) /* PMC1 selector */ +#define SPR_MMCR0_PMC2SEL(x) ((x) << 0) /* PMC2 selector */ +#define SPR_SGR 0x3b9 /* 4.. Storage Guarded Register */ +#define SPR_PMC1 0x3b9 /* .6. Performance Counter Register 1 */ +#define SPR_DCWR 0x3ba /* 4.. Data Cache Write-through Register */ +#define SPR_PMC2 0x3ba /* .6. Performance Counter Register 2 */ +#define SPR_SLER 0x3bb /* 4.. Storage Little Endian Register */ +#define SPR_SIA 0x3bb /* .6. Sampled Instruction Address */ +#define SPR_MMCR1 0x3bc /* .6. Monitor Mode Control Register 2 */ +#define SPR_MMCR1_PMC3SEL(x) ((x) << 27) /* PMC 3 selector */ +#define SPR_MMCR1_PMC4SEL(x) ((x) << 22) /* PMC 4 selector */ +#define SPR_MMCR1_PMC5SEL(x) ((x) << 17) /* PMC 5 selector */ +#define SPR_MMCR1_PMC6SEL(x) ((x) << 11) /* PMC 6 selector */ + +#define SPR_SU0R 0x3bc /* 4.. Storage User-defined 0 Register */ +#define SPR_DBCR1 0x3bd /* 4.. Debug Control Register 1 */ +#define SPR_PMC3 0x3bd /* .6. Performance Counter Register 3 */ +#define SPR_PMC4 0x3be /* .6. Performance Counter Register 4 */ +#define SPR_DMISS 0x3d0 /* .68 Data TLB Miss Address Register */ +#define SPR_DCMP 0x3d1 /* .68 Data TLB Compare Register */ +#define SPR_HASH1 0x3d2 /* .68 Primary Hash Address Register */ +#define SPR_ICDBDR 0x3d3 /* 4.. Instruction Cache Debug Data Register */ +#define SPR_HASH2 0x3d3 /* .68 Secondary Hash Address Register */ +#define SPR_ESR 0x3d4 /* 4.. Exception Syndrome Register */ +#define ESR_MCI 0x80000000 /* Machine check - instruction */ +#define ESR_PIL 0x08000000 /* Program interrupt - illegal */ +#define ESR_PPR 0x04000000 /* Program interrupt - privileged */ +#define ESR_PTR 0x02000000 /* Program interrupt - trap */ +#define ESR_DST 0x00800000 /* Data storage interrupt - store fault */ +#define ESR_DIZ 0x00800000 /* Data/instruction storage interrupt - zone fault */ +#define ESR_U0F 0x00008000 /* Data storage interrupt - U0 fault */ +#define SPR_IMISS 0x3d4 /* .68 Instruction TLB Miss Address Register */ +#define SPR_TLBMISS 0x3d4 /* .6. TLB Miss Address Register */ +#define SPR_DEAR 0x3d5 /* 4.. Data Error Address Register */ +#define SPR_ICMP 0x3d5 /* .68 Instruction TLB Compare Register */ +#define SPR_PTEHI 0x3d5 /* .6. Instruction TLB Compare Register */ +#define SPR_EVPR 0x3d6 /* 4.. Exception Vector Prefix Register */ +#define SPR_RPA 0x3d6 /* .68 Required Physical Address Register */ +#define SPR_PTELO 0x3d6 /* .6. Required Physical Address Register */ +#define SPR_TSR 0x3d8 /* 4.. Timer Status Register */ +#define TSR_ENW 0x80000000 /* Enable Next Watchdog */ +#define TSR_WIS 0x40000000 /* Watchdog Interrupt Status */ +#define TSR_WRS_MASK 0x30000000 /* Watchdog Reset Status */ +#define TSR_WRS_NONE 0x00000000 /* No watchdog reset has occurred */ +#define TSR_WRS_CORE 0x10000000 /* Core reset was forced by the watchdog */ +#define TSR_WRS_CHIP 0x20000000 /* Chip reset was forced by the watchdog */ +#define TSR_WRS_SYSTEM 0x30000000 /* System reset was forced by the watchdog */ +#define TSR_PIS 0x08000000 /* PIT Interrupt Status */ +#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ +#define SPR_TCR 0x3da /* 4.. Timer Control Register */ +#define TCR_WP_MASK 0xc0000000 /* Watchdog Period mask */ +#define TCR_WP_2_17 0x00000000 /* 2**17 clocks */ +#define TCR_WP_2_21 0x40000000 /* 2**21 clocks */ +#define TCR_WP_2_25 0x80000000 /* 2**25 clocks */ +#define TCR_WP_2_29 0xc0000000 /* 2**29 clocks */ +#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */ +#define TCR_WRC_NONE 0x00000000 /* No watchdog reset */ +#define TCR_WRC_CORE 0x10000000 /* Core reset */ +#define TCR_WRC_CHIP 0x20000000 /* Chip reset */ +#define TCR_WRC_SYSTEM 0x30000000 /* System reset */ +#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */ +#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ +#define TCR_FP_MASK 0x03000000 /* FIT Period */ +#define TCR_FP_2_9 0x00000000 /* 2**9 clocks */ +#define TCR_FP_2_13 0x01000000 /* 2**13 clocks */ +#define TCR_FP_2_17 0x02000000 /* 2**17 clocks */ +#define TCR_FP_2_21 0x03000000 /* 2**21 clocks */ +#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ +#define TCR_ARE 0x00400000 /* Auto Reload Enable */ +#define SPR_PIT 0x3db /* 4.. Programmable Interval Timer */ +#define SPR_SRR2 0x3de /* 4.. Save/Restore Register 2 */ +#define SPR_SRR3 0x3df /* 4.. Save/Restore Register 3 */ +#define SPR_DBSR 0x3f0 /* 4.. Debug Status Register */ +#define DBSR_IC 0x80000000 /* Instruction completion debug event */ +#define DBSR_BT 0x40000000 /* Branch Taken debug event */ +#define DBSR_EDE 0x20000000 /* Exception debug event */ +#define DBSR_TIE 0x10000000 /* Trap Instruction debug event */ +#define DBSR_UDE 0x08000000 /* Unconditional debug event */ +#define DBSR_IA1 0x04000000 /* IAC1 debug event */ +#define DBSR_IA2 0x02000000 /* IAC2 debug event */ +#define DBSR_DR1 0x01000000 /* DAC1 Read debug event */ +#define DBSR_DW1 0x00800000 /* DAC1 Write debug event */ +#define DBSR_DR2 0x00400000 /* DAC2 Read debug event */ +#define DBSR_DW2 0x00200000 /* DAC2 Write debug event */ +#define DBSR_IDE 0x00100000 /* Imprecise debug event */ +#define DBSR_IA3 0x00080000 /* IAC3 debug event */ +#define DBSR_IA4 0x00040000 /* IAC4 debug event */ +#define DBSR_MRR 0x00000300 /* Most recent reset */ +#define SPR_HID0 0x3f0 /* ..8 Hardware Implementation Register 0 */ +#define SPR_HID1 0x3f1 /* ..8 Hardware Implementation Register 1 */ +#define SPR_DBCR0 0x3f2 /* 4.. Debug Control Register 0 */ +#define DBCR0_EDM 0x80000000 /* External Debug Mode */ +#define DBCR0_IDM 0x40000000 /* Internal Debug Mode */ +#define DBCR0_RST_MASK 0x30000000 /* ReSeT */ +#define DBCR0_RST_NONE 0x00000000 /* No action */ +#define DBCR0_RST_CORE 0x10000000 /* Core reset */ +#define DBCR0_RST_CHIP 0x20000000 /* Chip reset */ +#define DBCR0_RST_SYSTEM 0x30000000 /* System reset */ +#define DBCR0_IC 0x08000000 /* Instruction Completion debug event */ +#define DBCR0_BT 0x04000000 /* Branch Taken debug event */ +#define DBCR0_EDE 0x02000000 /* Exception Debug Event */ +#define DBCR0_TDE 0x01000000 /* Trap Debug Event */ +#define DBCR0_IA1 0x00800000 /* IAC (Instruction Address Compare) 1 debug event */ +#define DBCR0_IA2 0x00400000 /* IAC 2 debug event */ +#define DBCR0_IA12 0x00200000 /* Instruction Address Range Compare 1-2 */ +#define DBCR0_IA12X 0x00100000 /* IA12 eXclusive */ +#define DBCR0_IA3 0x00080000 /* IAC 3 debug event */ +#define DBCR0_IA4 0x00040000 /* IAC 4 debug event */ +#define DBCR0_IA34 0x00020000 /* Instruction Address Range Compare 3-4 */ +#define DBCR0_IA34X 0x00010000 /* IA34 eXclusive */ +#define DBCR0_IA12T 0x00008000 /* Instruction Address Range Compare 1-2 range Toggle */ +#define DBCR0_IA34T 0x00004000 /* Instruction Address Range Compare 3-4 range Toggle */ +#define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ +#define SPR_IABR 0x3f2 /* ..8 Instruction Address Breakpoint Register 0 */ +#define SPR_HID2 0x3f3 /* ..8 Hardware Implementation Register 2 */ +#define SPR_IAC1 0x3f4 /* 4.. Instruction Address Compare 1 */ +#define SPR_IAC2 0x3f5 /* 4.. Instruction Address Compare 2 */ +#define SPR_DABR 0x3f5 /* .6. Data Address Breakpoint Register */ +#define SPR_DAC1 0x3f6 /* 4.. Data Address Compare 1 */ +#define SPR_DAC2 0x3f7 /* 4.. Data Address Compare 2 */ +#define SPR_L2PM 0x3f8 /* .6. L2 Private Memory Control Register */ +#define SPR_L2CR 0x3f9 /* .6. L2 Control Register */ +#define L2CR_L2E 0x80000000 /* 0: L2 enable */ +#define L2CR_L2PE 0x40000000 /* 1: L2 data parity enable */ +#define L2CR_L2SIZ 0x30000000 /* 2-3: L2 size */ +#define L2SIZ_2M 0x00000000 +#define L2SIZ_256K 0x10000000 +#define L2SIZ_512K 0x20000000 +#define L2SIZ_1M 0x30000000 +#define L2CR_L2CLK 0x0e000000 /* 4-6: L2 clock ratio */ +#define L2CLK_DIS 0x00000000 /* disable L2 clock */ +#define L2CLK_10 0x02000000 /* core clock / 1 */ +#define L2CLK_15 0x04000000 /* / 1.5 */ +#define L2CLK_20 0x08000000 /* / 2 */ +#define L2CLK_25 0x0a000000 /* / 2.5 */ +#define L2CLK_30 0x0c000000 /* / 3 */ +#define L2CR_L2RAM 0x01800000 /* 7-8: L2 RAM type */ +#define L2RAM_FLOWTHRU_BURST 0x00000000 +#define L2RAM_PIPELINE_BURST 0x01000000 +#define L2RAM_PIPELINE_LATE 0x01800000 +#define L2CR_L2DO 0x00400000 /* 9: L2 data-only. + Setting this bit disables instruction + caching. */ +#define L2CR_L2I 0x00200000 /* 10: L2 global invalidate. */ +#define L2CR_L2CTL 0x00100000 /* 11: L2 RAM control (ZZ enable). + Enables automatic operation of the + L2ZZ (low-power mode) signal. */ +#define L2CR_L2WT 0x00080000 /* 12: L2 write-through. */ +#define L2CR_L2TS 0x00040000 /* 13: L2 test support. */ +#define L2CR_L2OH 0x00030000 /* 14-15: L2 output hold. */ +#define L2CR_L2SL 0x00008000 /* 16: L2 DLL slow. */ +#define L2CR_L2DF 0x00004000 /* 17: L2 differential clock. */ +#define L2CR_L2BYP 0x00002000 /* 18: L2 DLL bypass. */ +#define L2CR_L2IP 0x00000001 /* 31: L2 global invalidate in */ + /* progress (read only). */ +#define SPR_L3CR 0x3fa /* .6. L3 Control Register */ +#define L3CR_L3E 0x80000000 /* 0: L3 enable */ +#define L3CR_L3SIZ 0x10000000 /* 3: L3 size (0=1MB, 1=2MB) */ +#define SPR_DCCR 0x3fa /* 4.. Data Cache Cachability Register */ +#define SPR_ICCR 0x3fb /* 4.. Instruction Cache Cachability Register */ +#define SPR_THRM1 0x3fc /* .6. Thermal Management Register */ +#define SPR_THRM2 0x3fd /* .6. Thermal Management Register */ +#define SPR_THRM_TIN 0x80000000 /* Thermal interrupt bit (RO) */ +#define SPR_THRM_TIV 0x40000000 /* Thermal interrupt valid (RO) */ +#define SPR_THRM_THRESHOLD(x) ((x) << 23) /* Thermal sensor threshold */ +#define SPR_THRM_TID 0x00000004 /* Thermal interrupt direction */ +#define SPR_THRM_TIE 0x00000002 /* Thermal interrupt enable */ +#define SPR_THRM_VALID 0x00000001 /* Valid bit */ +#define SPR_THRM3 0x3fe /* .6. Thermal Management Register */ +#define SPR_THRM_TIMER(x) ((x) << 1) /* Sampling interval timer */ +#define SPR_THRM_ENABLE 0x00000001 /* TAU Enable */ +#define SPR_FPECR 0x3fe /* .6. Floating-Point Exception Cause Register */ +#define SPR_PIR 0x3ff /* .6. Processor Identification Register */ + +/* Time Base Register declarations */ +#define TBR_TBL 0x10c /* 468 Time Base Lower */ +#define TBR_TBU 0x10d /* 468 Time Base Upper */ + +/* Performance counter declarations */ +#define PMC_OVERFLOW 0x80000000 /* Counter has overflowed */ + +/* The first five countable [non-]events are common to all the PMC's */ +#define PMCN_NONE 0 /* Count nothing */ +#define PMCN_CYCLES 1 /* Processor cycles */ +#define PMCN_ICOMP 2 /* Instructions completed */ +#define PMCN_TBLTRANS 3 /* TBL bit transitions */ +#define PCMN_IDISPATCH 4 /* Instructions dispatched */ + +#endif /* !_POWERPC_SPR_H_ */ diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c index c8a484b..6ff94de 100644 --- a/sys/powerpc/powerpc/genassym.c +++ b/sys/powerpc/powerpc/genassym.c @@ -62,12 +62,14 @@ ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb)); +ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap)); ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); ASSYM(MTX_RECURSECNT, offsetof(struct mtx, mtx_recurse)); ASSYM(PM_KERNELSR, offsetof(struct pmap, pm_sr[KERNEL_SR])); -ASSYM(PM_USERSR, offsetof(struct pmap, pm_sr[USER_SR])); +ASSYM(PM_USRSR, offsetof(struct pmap, pm_sr[USER_SR])); +ASSYM(PM_SR, offsetof(struct pmap, pm_sr)); ASSYM(FRAMELEN, FRAMELEN); ASSYM(FRAME_0, offsetof(struct trapframe, fixreg[0])); @@ -86,6 +88,43 @@ ASSYM(FRAME_EXC, offsetof(struct trapframe, exc)); ASSYM(SFRAMELEN, roundup(sizeof(struct switchframe), 16)); +ASSYM(IFRAMELEN, IFRAMELEN); +ASSYM(IFRAME_R1, offsetof(struct intrframe, r1)); +ASSYM(IFRAME_SRR1, offsetof(struct intrframe, srr1)); +ASSYM(IFRAME_SRR0, offsetof(struct intrframe, srr0)); +ASSYM(IFRAME_PRI, offsetof(struct intrframe, pri)); +ASSYM(IFRAME_INTR_DEPTH, offsetof(struct intrframe, intr_depth)); +ASSYM(IFRAME_VRSAVE, offsetof(struct intrframe, vrsave)); +ASSYM(IFRAME_CTR, offsetof(struct intrframe, ctr)); +ASSYM(IFRAME_XER, offsetof(struct intrframe, xer)); +ASSYM(IFRAME_CR, offsetof(struct intrframe, cr)); +ASSYM(IFRAME_LR, offsetof(struct intrframe, lr)); +ASSYM(IFRAME_R12, offsetof(struct intrframe, r12)); +ASSYM(IFRAME_R11, offsetof(struct intrframe, r11)); +ASSYM(IFRAME_R10, offsetof(struct intrframe, r10)); +ASSYM(IFRAME_R9, offsetof(struct intrframe, r9)); +ASSYM(IFRAME_R8, offsetof(struct intrframe, r8)); +ASSYM(IFRAME_R7, offsetof(struct intrframe, r7)); +ASSYM(IFRAME_R6, offsetof(struct intrframe, r6)); +ASSYM(IFRAME_R5, offsetof(struct intrframe, r5)); +ASSYM(IFRAME_R4, offsetof(struct intrframe, r4)); +ASSYM(IFRAME_R3, offsetof(struct intrframe, r3)); +ASSYM(IFRAME_R0, offsetof(struct intrframe, r0)); + +ASSYM(SPFRAMELEN, SPFRAMELEN); +ASSYM(SPFRAME_R1, offsetof(struct spillframe, r1)); +ASSYM(SPFRAME_R12, offsetof(struct spillframe, r12)); +ASSYM(SPFRAME_R11, offsetof(struct spillframe, r11)); +ASSYM(SPFRAME_R10, offsetof(struct spillframe, r10)); +ASSYM(SPFRAME_R9, offsetof(struct spillframe, r9)); +ASSYM(SPFRAME_R8, offsetof(struct spillframe, r8)); +ASSYM(SPFRAME_R7, offsetof(struct spillframe, r7)); +ASSYM(SPFRAME_R6, offsetof(struct spillframe, r6)); +ASSYM(SPFRAME_R5, offsetof(struct spillframe, r5)); +ASSYM(SPFRAME_R4, offsetof(struct spillframe, r4)); +ASSYM(SPFRAME_R3, offsetof(struct spillframe, r3)); +ASSYM(SPFRAME_R0, offsetof(struct spillframe, r0)); + ASSYM(CF_FUNC, offsetof(struct callframe, cf_func)); ASSYM(CF_ARG0, offsetof(struct callframe, cf_arg0)); ASSYM(CF_ARG1, offsetof(struct callframe, cf_arg1)); @@ -100,3 +139,7 @@ ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(TD_PROC, offsetof(struct thread, td_proc)); ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); + +ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace)); + +ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap)); diff --git a/sys/powerpc/powerpc/locore.S b/sys/powerpc/powerpc/locore.S index 29a3b9c..fa231e8 100644 --- a/sys/powerpc/powerpc/locore.S +++ b/sys/powerpc/powerpc/locore.S @@ -65,6 +65,7 @@ #include <machine/trap.h> #include <machine/param.h> #include <machine/sr.h> +#include <machine/spr.h> #include <machine/psl.h> #include <machine/asm.h> @@ -122,6 +123,9 @@ GLOBAL(ofmsr) GLOBAL(powersave) .long 0 +#define INTSTK 8192 /* 8K interrupt stack */ +#define SPILLSTK 4096 /* 4K spill stack */ + /* * File-scope for locore.S */ @@ -391,929 +395,6 @@ ofw_back: blr /* - * Data used during primary/secondary traps/interrupts - */ -#define tempsave 0x2e0 /* primary save area for trap handling */ -#define disisave 0x3e0 /* primary save area for dsi/isi traps */ - -#define INTSTK (8*1024) /* 8K interrupt stack */ - .data - .align 4 -intstk: - .space INTSTK /* interrupt stack */ - -GLOBAL(intr_depth) - .long -1 /* in-use marker */ - -#define SPILLSTK 1024 /* 1K spill stack */ - - .comm spillstk,SPILLSTK,8 - -/* - * This code gets copied to all the trap vectors - * (except ISI/DSI, ALI, the interrupts, and possibly the debugging - * traps when using IPKDB). - */ - .text - .globl trapcode,trapsize -trapcode: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 31 - mtcr 31 - bc 4,17,1f /* branch if PSL_PR is clear */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ -1: - bla s_trap -trapsize = .-trapcode - -/* - * For ALI: has to save DSISR and DAR - */ - .globl alitrap,alisize -alitrap: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mfdar 30 - mfdsisr 31 - stmw 30,tempsave+16(0) - mflr 28 /* save LR */ - mfcr 29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 31 - mtcr 31 - bc 4,17,1f /* branch if PSL_PR is clear */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ -1: - bla s_trap -alisize = .-alitrap - -/* - * Similar to the above for DSI - * Has to handle BAT spills - * and standard pagetable spills - */ - .globl dsitrap,dsisize -dsitrap: - stmw 28,disisave(0) /* free r28-r31 */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - mtsprg 2,30 /* in SPRG2 */ - mfsrr1 31 /* test kernel mode */ - mtcr 31 - bc 12,17,1f /* branch if PSL_PR is set */ - mfdar 31 /* get fault address */ - rlwinm 31,31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis 31,31,battable@ha - lwz 30,battable@l(31) - mtcr 30 - bc 4,30,1f /* branch if supervisor valid is - false */ - /* get batl */ - lwz 31,battable+4@l(31) -/* We randomly use the highest two bat registers here */ - mftb 28 - andi. 28,28,1 - bne 2f - mtdbatu 2,30 - mtdbatl 2,31 - b 3f -2: - mtdbatu 3,30 - mtdbatl 3,31 -3: - mfsprg 30,2 /* restore XER */ - mtxer 30 - mtcr 29 /* restore CR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ -1: - mflr 28 /* save LR */ - bla s_dsitrap -dsisize = .-dsitrap - -/* - * Similar to the above for ISI - */ - .globl isitrap,isisize -isitrap: - stmw 28,disisave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfsrr1 31 /* test kernel mode */ - mtcr 31 - bc 12,17,1f /* branch if PSL_PR is set */ - mfsrr0 31 /* get fault address */ - rlwinm 31,31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis 31,31,battable@ha - lwz 30,battable@l(31) - mtcr 30 - bc 4,30,1f /* branch if supervisor valid is - false */ - mtibatu 3,30 - - /* get batl */ - lwz 30,battable+4@l(31) - mtibatl 3,30 - - mtcr 29 /* restore CR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ -1: - bla s_isitrap -isisize = .-isitrap - -/* - * This one for the external interrupt handler. - */ - .globl extint,extsize -extint: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - lis 1,intstk+INTSTK@ha /* get interrupt stack */ - addi 1,1,intstk+INTSTK@l - lwz 31,0(1) /* were we already running on intstk? */ - addic. 31,31,1 - stw 31,0(1) - beq 1f - mfsprg 1,1 /* yes, get old SP */ -1: - ba extintr -extsize = .-extint - -/* - * And this one for the decrementer interrupt handler. - */ - .globl decrint,decrsize -decrint: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - lis 28,decrnest@ha - lwz 29,decrnest@l(28) - cmplwi 0,29,0 - bne 2f - li 29,1 - stw 29,decrnest@l(28) - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - lis 1,intstk+INTSTK@ha /* get interrupt stack */ - addi 1,1,intstk+INTSTK@l - lwz 31,0(1) /* were we already running on intstk? */ - addic. 31,31,1 - stw 31,0(1) - beq 1f - mfsprg 1,1 /* yes, get old SP */ -1: - ba decrintr -2: - lmw 28,tempsave(0) - rfi -decrsize = .-decrint - -/* - * Now the tlb software load for 603 processors: - * (Code essentially from the 603e User Manual, Chapter 5, but - * corrected a lot.) - */ -#define DMISS 976 -#define DCMP 977 -#define HASH1 978 -#define HASH2 979 -#define IMISS 980 -#define ICMP 981 -#define RPA 982 - - .globl tlbimiss,tlbimsize -tlbimiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,ICMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - andi. 3,1,8 /* check G-bit */ - bne 4f /* if guarded, take ISI */ - mtctr 0 /* restore counter */ - mfspr 0,IMISS /* get the miss address for the tlbli */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - ori 1,1,0x100 /* set the reference bit */ - mtspr RPA,1 /* set the pte */ - srwi 1,1,8 /* get byte 7 of pte */ - tlbli 0 /* load the itlb */ - stb 1,6(2) /* update page table */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -4: /* guarded */ - mfsrr1 3 - andi. 2,3,0xffff /* clean upper srr1 */ - oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ - b 6f -5: /* not found anywhere */ - mfsrr1 3 - andi. 2,3,0xffff /* clean upper srr1 */ - oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ -6: - mtctr 0 /* restore counter */ - mtsrr1 2 - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_ISI -tlbimsize = .-tlbimiss - - .globl tlbdlmiss,tlbdlmsize -tlbdlmiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,DCMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - mtctr 0 /* restore counter */ - mfspr 0,DMISS /* get the miss address for the tlbld */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - ori 1,1,0x100 /* set the reference bit */ - mtspr RPA,1 /* set the pte */ - srwi 1,1,8 /* get byte 7 of pte */ - tlbld 0 /* load the dtlb */ - stb 1,6(2) /* update page table */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -5: /* not found anywhere */ - mfsrr1 3 - lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ - mtctr 0 /* restore counter */ - andi. 2,3,0xffff /* clean upper srr1 */ - mtsrr1 2 - mtdsisr 1 /* load the dsisr */ - mfspr 1,DMISS /* get the miss address */ - mtdar 1 /* put in dar */ - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_DSI -tlbdlmsize = .-tlbdlmiss - - .globl tlbdsmiss,tlbdsmsize -tlbdsmiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,DCMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - andi. 3,1,0x80 /* check the C-bit */ - beq 4f -5: - mtctr 0 /* restore counter */ - mfspr 0,DMISS /* get the miss address for the tlbld */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - mtspr RPA,1 /* set the pte */ - tlbld 0 /* load the dtlb */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -4: /* found, but C-bit = 0 */ - rlwinm. 3,1,30,0,1 /* test PP */ - bge- 7f - andi. 3,1,1 - beq+ 8f -9: /* found, but protection violation (PP==00)*/ - mfsrr1 3 - lis 1,0xa000000@h /* indicate protection violation - on store */ - b 1f -7: /* found, PP=1x */ - mfspr 3,DMISS /* get the miss address */ - mfsrin 1,3 /* get the segment register */ - mfsrr1 3 - rlwinm 3,3,18,31,31 /* get PR-bit */ - rlwnm. 2,2,3,1,1 /* get the key */ - bne- 9b /* protection violation */ -8: /* found, set reference/change bits */ - lwz 1,4(2) /* reload tlb entry */ - ori 1,1,0x180 - sth 1,6(2) - b 5b -5: /* not found anywhere */ - mfsrr1 3 - lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ - /* dsisr<6> to flag store */ -1: - mtctr 0 /* restore counter */ - andi. 2,3,0xffff /* clean upper srr1 */ - mtsrr1 2 - mtdsisr 1 /* load the dsisr */ - mfspr 1,DMISS /* get the miss address */ - mtdar 1 /* put in dar */ - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_DSI -tlbdsmsize = .-tlbdsmiss - -#ifdef DDB -#define ddbsave 0xde0 /* primary save area for DDB */ -/* - * In case of DDB we want a separate trap catcher for it - */ - .local ddbstk - .comm ddbstk,INTSTK,8 /* ddb stack */ - - .globl ddblow,ddbsize -ddblow: - mtsprg 1,1 /* save SP */ - stmw 28,ddbsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - lis 1,ddbstk+INTSTK@ha /* get new SP */ - addi 1,1,ddbstk+INTSTK@l - bla ddbtrap -ddbsize = .-ddblow -#endif /* DDB */ - -#ifdef IPKDB -#define ipkdbsave 0xde0 /* primary save area for IPKDB */ -/* - * In case of IPKDB we want a separate trap catcher for it - */ - - .local ipkdbstk - .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ - - .globl ipkdblow,ipkdbsize -ipkdblow: - mtsprg 1,1 /* save SP */ - stmw 28,ipkdbsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - lis 1,ipkdbstk+INTSTK@ha /* get new SP */ - addi 1,1,ipkdbstk+INTSTK@l - bla ipkdbtrap -ipkdbsize = .-ipkdblow -#endif /* IPKDB */ - -/* - * FRAME_SETUP assumes: - * SPRG1 SP (1) - * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) - * 28 LR - * 29 CR - * 1 kernel stack - * LR trap type - * SRR0/1 as at start of trap - */ -#define FRAME_SETUP(savearea) \ -/* Have to enable translation to allow access of kernel stack: */ \ - mfsrr0 30; \ - mfsrr1 31; \ - stmw 30,savearea+24(0); \ - mfmsr 30; \ - ori 30,30,(PSL_DR|PSL_IR); \ - mtmsr 30; \ - isync; \ - mfsprg 31,1; \ - stwu 31,-FRAMELEN(1); \ - stw 0,FRAME_0+8(1); \ - stw 31,FRAME_1+8(1); \ - stw 28,FRAME_LR+8(1); \ - stw 29,FRAME_CR+8(1); \ - lmw 28,savearea(0); \ - stmw 2,FRAME_2+8(1); \ - lmw 28,savearea+16(0); \ - mfxer 3; \ - mfctr 4; \ - mflr 5; \ - andi. 5,5,0xff00; \ - stw 3,FRAME_XER+8(1); \ - stw 4,FRAME_CTR+8(1); \ - stw 5,FRAME_EXC+8(1); \ - stw 28,FRAME_DAR+8(1); \ - stw 29,FRAME_DSISR+8(1); \ - stw 30,FRAME_SRR0+8(1); \ - stw 31,FRAME_SRR1+8(1) - -#define FRAME_LEAVE(savearea) \ -/* Now restore regs: */ \ - lwz 2,FRAME_SRR0+8(1); \ - lwz 3,FRAME_SRR1+8(1); \ - lwz 4,FRAME_CTR+8(1); \ - lwz 5,FRAME_XER+8(1); \ - lwz 6,FRAME_LR+8(1); \ - lwz 7,FRAME_CR+8(1); \ - stw 2,savearea(0); \ - stw 3,savearea+4(0); \ - mtctr 4; \ - mtxer 5; \ - mtlr 6; \ - mtsprg 1,7; /* save cr */ \ - lmw 2,FRAME_2+8(1); \ - lwz 0,FRAME_0+8(1); \ - lwz 1,FRAME_1+8(1); \ - mtsprg 2,2; /* save r2 & r3 */ \ - mtsprg 3,3; \ -/* Disable translation, machine check and recoverability: */ \ - mfmsr 2; \ - andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ - mtmsr 2; \ - isync; \ -/* Decide whether we return to user mode: */ \ - lwz 3,savearea+4(0); \ - mtcr 3; \ - bc 4,17,1f; /* branch if PSL_PR is false */ \ -/* Restore user & kernel access SR: */ \ -/* lis 2,curpm@ha; get real address of pmap */ \ -/* lwz 2,curpm@l(2); */ \ -/* lwz 3,PM_USRSR(2); */ \ -/* mtsr USER_SR,3; */ \ -/* lwz 3,PM_KERNELSR(2); */ \ -/* mtsr KERNEL_SR,3; */ \ -1: mfsprg 2,1; /* restore cr */ \ - mtcr 2; \ - lwz 2,savearea(0); \ - lwz 3,savearea+4(0); \ - mtsrr0 2; \ - mtsrr1 3; \ - mfsprg 2,2; /* restore r2 & r3 */ \ - mfsprg 3,3 - -/* - * Preamble code for DSI/ISI traps - */ -disitrap: - lmw 30,disisave(0) - stmw 30,tempsave(0) - lmw 30,disisave+8(0) - stmw 30,tempsave+8(0) - mfdar 30 - mfdsisr 31 - stmw 30,tempsave+16(0) -realtrap: -/* Test whether we already had PR set */ - mfsrr1 1 - mtcr 1 - mfsprg 1,1 /* restore SP (might have been - overwritten) */ - bc 4,17,s_trap /* branch if PSL_PR is false */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ - -/* - * Now the common trap catching code. - */ -s_trap: -/* First have to enable KERNEL mapping */ - lis 31,KERNEL_SEGMENT@h - ori 31,31,KERNEL_SEGMENT@l - mtsr KERNEL_SR,31 - FRAME_SETUP(tempsave) -/* Now we can recover interrupts again: */ - mfmsr 7 - ori 7,7,(PSL_EE|PSL_FP|PSL_ME|PSL_RI)@l - mtmsr 7 - isync -/* Call C trap code: */ - addi 3,1,8 - mr 30,3 - bl trap - mr 3,30 - bl ast - FRAME_LEAVE(tempsave) - rfi - -/* - * DSI second stage fault handler - */ -s_dsitrap: - mfdsisr 31 /* test whether this may be a - spill fault */ - mtcr 31 - mtsprg 1,1 /* save SP */ - bc 4,1,disitrap /* branch if table miss is false */ - lis 1,spillstk+SPILLSTK@ha - addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ - stwu 1,-52(1) - stw 0,48(1) /* save non-volatile registers */ - stw 3,44(1) - stw 4,40(1) - stw 5,36(1) - stw 6,32(1) - stw 7,28(1) - stw 8,24(1) - stw 9,20(1) - stw 10,16(1) - stw 11,12(1) - stw 12,8(1) - mflr 30 /* save trap type */ - mfctr 31 /* & CTR */ - mfdar 3 -s_pte_spill: - bl pmap_pte_spill /* try a spill */ - or. 3,3,3 - mtctr 31 /* restore CTR */ - mtlr 30 /* and trap type */ - mfsprg 31,2 /* get saved XER */ - mtxer 31 /* restore XER */ - lwz 12,8(1) /* restore non-volatile registers */ - lwz 11,12(1) - lwz 10,16(1) - lwz 9,20(1) - lwz 8,24(1) - lwz 7,28(1) - lwz 6,32(1) - lwz 5,36(1) - lwz 4,40(1) - lwz 3,44(1) - lwz 0,48(1) - beq disitrap - mfsprg 1,1 /* restore SP */ - mtcr 29 /* restore CR */ - mtlr 28 /* restore LR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ - -/* - * ISI second stage fault handler - */ -s_isitrap: - mfsrr1 31 /* test whether this may be a - spill fault */ - mtcr 31 - mtsprg 1,1 /* save SP */ - bc 4,1,disitrap /* branch if table miss is false */ - lis 1,spillstk+SPILLSTK@ha - addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ - stwu 1,-52(1) - stw 0,48(1) /* save non-volatile registers */ - stw 3,44(1) - stw 4,40(1) - stw 5,36(1) - stw 6,32(1) - stw 7,28(1) - stw 8,24(1) - stw 9,20(1) - stw 10,16(1) - stw 11,12(1) - stw 12,8(1) - mfxer 30 /* save XER */ - mtsprg 2,30 - mflr 30 /* save trap type */ - mfctr 31 /* & ctr */ - mfsrr0 3 - b s_pte_spill /* above */ - -/* - * External interrupt second level handler - */ -#define INTRENTER \ -/* Save non-volatile registers: */ \ - stwu 1,-88(1); /* temporarily */ \ - stw 0,84(1); \ - mfsprg 0,1; /* get original SP */ \ - stw 0,0(1); /* and store it */ \ - stw 3,80(1); \ - stw 4,76(1); \ - stw 5,72(1); \ - stw 6,68(1); \ - stw 7,64(1); \ - stw 8,60(1); \ - stw 9,56(1); \ - stw 10,52(1); \ - stw 11,48(1); \ - stw 12,44(1); \ - stw 28,40(1); /* saved LR */ \ - stw 29,36(1); /* saved CR */ \ - stw 30,32(1); /* saved XER */ \ - lmw 28,tempsave(0); /* restore r28-r31 */ \ - mfctr 6; \ - lis 5,intr_depth@ha; \ - lwz 5,intr_depth@l(5); \ - mfsrr0 4; \ - mfsrr1 3; \ - stw 6,28(1); \ - stw 5,20(1); \ - stw 4,12(1); \ - stw 3,8(1); \ -/* interrupts are recoverable here, and enable translation */ \ - lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ - ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ - mtsr KERNEL_SR,3; \ - mfmsr 5; \ - ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ - mtmsr 5; \ - isync - - .globl extint_call -extintr: - INTRENTER -extint_call: - bl extint_call /* to be filled in later */ - -intr_exit: -/* Disable interrupts (should already be disabled) and MMU here: */ - mfmsr 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l - mtmsr 3 - isync -/* restore possibly overwritten registers: */ - lwz 12,44(1) - lwz 11,48(1) - lwz 10,52(1) - lwz 9,56(1) - lwz 8,60(1) - lwz 7,64(1) - lwz 6,8(1) - lwz 5,12(1) - lwz 4,28(1) - lwz 3,32(1) - mtsrr1 6 - mtsrr0 5 - mtctr 4 - mtxer 3 -/* Returning to user mode? */ - mtcr 6 /* saved SRR1 */ - bc 4,17,1f /* branch if PSL_PR is false */ - mfsprg 3,0 /* get pcpu */ - lwz 3,PC_CURPCB(3) /* get curpcb from pcpu */ - lwz 3,PCB_PMR(3) /* get pmap real address from curpcb */ - mtsr KERNEL_SR,3 -/* Setup for entry to realtrap: */ - lwz 3,0(1) /* get saved SP */ - mtsprg 1,3 -#if 0 /* XXX */ - li 6,EXC_AST -#endif - stmw 28,tempsave(0) /* establish tempsave again */ - mtlr 6 - lwz 28,40(1) /* saved LR */ - lwz 29,36(1) /* saved CR */ - lwz 6,68(1) - lwz 5,72(1) - lwz 4,76(1) - lwz 3,80(1) - lwz 0,84(1) - lis 30,intr_depth@ha /* adjust reentrancy count */ - lwz 31,intr_depth@l(30) - addi 31,31,-1 - stw 31,intr_depth@l(30) - b realtrap /* XXX: should call ast(frame ptr) */ -1: -/* Here is the normal exit of extintr: */ - lwz 5,36(1) - lwz 6,40(1) - mtcr 5 - mtlr 6 - lwz 6,68(1) - lwz 5,72(1) - lis 3,intr_depth@ha /* adjust reentrancy count */ - lwz 4,intr_depth@l(3) - addi 4,4,-1 - stw 4,intr_depth@l(3) - lwz 4,76(1) - lwz 3,80(1) - lwz 0,84(1) - lwz 1,0(1) - rfi - -/* - * Decrementer interrupt second level handler - */ -decrintr: - INTRENTER - addi 3,1,8 /* intr frame */ - bl decr_intr - lis 28,decrnest@ha - xor 29,29,29 - stw 29,decrnest@l(28) - b intr_exit - -#ifdef DDB -/* - * Deliberate entry to ddbtrap - */ - .globl ddb_trap -ddb_trap: - mtsprg 1,1 - mfmsr 3 - mtsrr1 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI)@l - mtmsr 3 /* disable interrupts */ - isync - stmw 28,ddbsave(0) - mflr 28 - li 29,EXC_BPT - mtlr 29 - mfcr 29 - mtsrr0 28 - -/* - * Now the ddb trap catching code. - */ -ddbtrap: - FRAME_SETUP(ddbsave) -/* Call C trap code: */ - addi 3,1,8 - bl ddb_trap_glue - or. 3,3,3 - bne ddbleave -/* This wasn't for DDB, so switch to real trap: */ - lwz 3,FRAME_EXC+8(1) /* save exception */ - stw 3,ddbsave+8(0) - FRAME_LEAVE(ddbsave) - mtsprg 1,1 /* prepare for entrance to realtrap */ - stmw 28,tempsave(0) - mflr 28 - mfcr 29 - lwz 31,ddbsave+8(0) - mtlr 31 - b realtrap -ddbleave: - FRAME_LEAVE(ddbsave) - rfi -#endif /* DDB */ - -#ifdef IPKDB -/* - * Deliberate entry to ipkdbtrap - */ - .globl ipkdb_trap -ipkdb_trap: - mtsprg 1,1 - mfmsr 3 - mtsrr1 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI)@l - mtmsr 3 /* disable interrupts */ - isync - stmw 28,ipkdbsave(0) - mflr 28 - li 29,EXC_BPT - mtlr 29 - mfcr 29 - mtsrr0 28 - -/* - * Now the ipkdb trap catching code. - */ -ipkdbtrap: - FRAME_SETUP(ipkdbsave) -/* Call C trap code: */ - addi 3,1,8 - bl ipkdb_trap_glue - or. 3,3,3 - bne ipkdbleave -/* This wasn't for IPKDB, so switch to real trap: */ - lwz 3,FRAME_EXC+8(1) /* save exception */ - stw 3,ipkdbsave+8(0) - FRAME_LEAVE(ipkdbsave) - mtsprg 1,1 /* prepare for entrance to realtrap */ - stmw 28,tempsave(0) - mflr 28 - mfcr 29 - lwz 31,ipkdbsave+8(0) - mtlr 31 - b realtrap -ipkdbleave: - FRAME_LEAVE(ipkdbsave) - rfi - -ipkdbfault: - ba _ipkdbfault -_ipkdbfault: - mfsrr0 3 - addi 3,3,4 - mtsrr0 3 - li 3,-1 - rfi - -/* - * int ipkdbfbyte(unsigned char *p) - */ - .globl ipkdbfbyte -ipkdbfbyte: - li 9,EXC_DSI /* establish new fault routine */ - lwz 5,0(9) - lis 6,ipkdbfault@ha - lwz 6,ipkdbfault@l(6) - stw 6,0(9) -#ifdef IPKDBUSERHACK - lis 8,ipkdbsr@ha - lwz 8,ipkdbsr@l(8) - mtsr USER_SR,8 - isync -#endif - dcbst 0,9 /* flush data... */ - sync - icbi 0,9 /* and instruction caches */ - lbz 3,0(3) /* fetch data */ - stw 5,0(9) /* restore previous fault handler */ - dcbst 0,9 /* and flush data... */ - sync - icbi 0,9 /* and instruction caches */ - blr - -/* - * int ipkdbsbyte(unsigned char *p, int c) - */ - .globl ipkdbsbyte -ipkdbsbyte: - li 9,EXC_DSI /* establish new fault routine */ - lwz 5,0(9) - lis 6,ipkdbfault@ha - lwz 6,ipkdbfault@l(6) - stw 6,0(9) -#ifdef IPKDBUSERHACK - lis 8,ipkdbsr@ha - lwz 8,ipkdbsr@l(8) - mtsr USER_SR,8 - isync -#endif - dcbst 0,9 /* flush data... */ - sync - icbi 0,9 /* and instruction caches */ - mr 6,3 - xor 3,3,3 - stb 4,0(6) - dcbst 0,6 /* Now do appropriate flushes - to data... */ - sync - icbi 0,6 /* and instruction caches */ - stw 5,0(9) /* restore previous fault handler */ - dcbst 0,9 /* and flush data... */ - sync - icbi 0,9 /* and instruction caches */ - blr -#endif /* IPKDB */ - -/* * int setfault() * * Similar to setjmp to setup for handling faults on accesses to user memory. @@ -1326,7 +407,8 @@ setfault: mflr 0 mfcr 12 mfsprg 4,0 - lwz 4,PC_CURPCB(4) + lwz 4,PC_CURTHREAD(4) + lwz 4,TD_PCB(4) stw 3,PCB_ONFAULT(4) stw 0,0(3) stw 1,4(3) @@ -1335,15 +417,4 @@ setfault: xor 3,3,3 blr -/* - * Signal "trampoline" code. - */ - .globl sigcode -sigcode: - b sys_exit -esigcode: - .data -GLOBAL(szsigcode) - .long esigcode-sigcode - .text - +#include <powerpc/powerpc/trap_subr.S> diff --git a/sys/powerpc/powerpc/locore.s b/sys/powerpc/powerpc/locore.s index 29a3b9c..fa231e8 100644 --- a/sys/powerpc/powerpc/locore.s +++ b/sys/powerpc/powerpc/locore.s @@ -65,6 +65,7 @@ #include <machine/trap.h> #include <machine/param.h> #include <machine/sr.h> +#include <machine/spr.h> #include <machine/psl.h> #include <machine/asm.h> @@ -122,6 +123,9 @@ GLOBAL(ofmsr) GLOBAL(powersave) .long 0 +#define INTSTK 8192 /* 8K interrupt stack */ +#define SPILLSTK 4096 /* 4K spill stack */ + /* * File-scope for locore.S */ @@ -391,929 +395,6 @@ ofw_back: blr /* - * Data used during primary/secondary traps/interrupts - */ -#define tempsave 0x2e0 /* primary save area for trap handling */ -#define disisave 0x3e0 /* primary save area for dsi/isi traps */ - -#define INTSTK (8*1024) /* 8K interrupt stack */ - .data - .align 4 -intstk: - .space INTSTK /* interrupt stack */ - -GLOBAL(intr_depth) - .long -1 /* in-use marker */ - -#define SPILLSTK 1024 /* 1K spill stack */ - - .comm spillstk,SPILLSTK,8 - -/* - * This code gets copied to all the trap vectors - * (except ISI/DSI, ALI, the interrupts, and possibly the debugging - * traps when using IPKDB). - */ - .text - .globl trapcode,trapsize -trapcode: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 31 - mtcr 31 - bc 4,17,1f /* branch if PSL_PR is clear */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ -1: - bla s_trap -trapsize = .-trapcode - -/* - * For ALI: has to save DSISR and DAR - */ - .globl alitrap,alisize -alitrap: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mfdar 30 - mfdsisr 31 - stmw 30,tempsave+16(0) - mflr 28 /* save LR */ - mfcr 29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 31 - mtcr 31 - bc 4,17,1f /* branch if PSL_PR is clear */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ -1: - bla s_trap -alisize = .-alitrap - -/* - * Similar to the above for DSI - * Has to handle BAT spills - * and standard pagetable spills - */ - .globl dsitrap,dsisize -dsitrap: - stmw 28,disisave(0) /* free r28-r31 */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - mtsprg 2,30 /* in SPRG2 */ - mfsrr1 31 /* test kernel mode */ - mtcr 31 - bc 12,17,1f /* branch if PSL_PR is set */ - mfdar 31 /* get fault address */ - rlwinm 31,31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis 31,31,battable@ha - lwz 30,battable@l(31) - mtcr 30 - bc 4,30,1f /* branch if supervisor valid is - false */ - /* get batl */ - lwz 31,battable+4@l(31) -/* We randomly use the highest two bat registers here */ - mftb 28 - andi. 28,28,1 - bne 2f - mtdbatu 2,30 - mtdbatl 2,31 - b 3f -2: - mtdbatu 3,30 - mtdbatl 3,31 -3: - mfsprg 30,2 /* restore XER */ - mtxer 30 - mtcr 29 /* restore CR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ -1: - mflr 28 /* save LR */ - bla s_dsitrap -dsisize = .-dsitrap - -/* - * Similar to the above for ISI - */ - .globl isitrap,isisize -isitrap: - stmw 28,disisave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfsrr1 31 /* test kernel mode */ - mtcr 31 - bc 12,17,1f /* branch if PSL_PR is set */ - mfsrr0 31 /* get fault address */ - rlwinm 31,31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis 31,31,battable@ha - lwz 30,battable@l(31) - mtcr 30 - bc 4,30,1f /* branch if supervisor valid is - false */ - mtibatu 3,30 - - /* get batl */ - lwz 30,battable+4@l(31) - mtibatl 3,30 - - mtcr 29 /* restore CR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ -1: - bla s_isitrap -isisize = .-isitrap - -/* - * This one for the external interrupt handler. - */ - .globl extint,extsize -extint: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - lis 1,intstk+INTSTK@ha /* get interrupt stack */ - addi 1,1,intstk+INTSTK@l - lwz 31,0(1) /* were we already running on intstk? */ - addic. 31,31,1 - stw 31,0(1) - beq 1f - mfsprg 1,1 /* yes, get old SP */ -1: - ba extintr -extsize = .-extint - -/* - * And this one for the decrementer interrupt handler. - */ - .globl decrint,decrsize -decrint: - mtsprg 1,1 /* save SP */ - stmw 28,tempsave(0) /* free r28-r31 */ - lis 28,decrnest@ha - lwz 29,decrnest@l(28) - cmplwi 0,29,0 - bne 2f - li 29,1 - stw 29,decrnest@l(28) - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - mfxer 30 /* save XER */ - lis 1,intstk+INTSTK@ha /* get interrupt stack */ - addi 1,1,intstk+INTSTK@l - lwz 31,0(1) /* were we already running on intstk? */ - addic. 31,31,1 - stw 31,0(1) - beq 1f - mfsprg 1,1 /* yes, get old SP */ -1: - ba decrintr -2: - lmw 28,tempsave(0) - rfi -decrsize = .-decrint - -/* - * Now the tlb software load for 603 processors: - * (Code essentially from the 603e User Manual, Chapter 5, but - * corrected a lot.) - */ -#define DMISS 976 -#define DCMP 977 -#define HASH1 978 -#define HASH2 979 -#define IMISS 980 -#define ICMP 981 -#define RPA 982 - - .globl tlbimiss,tlbimsize -tlbimiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,ICMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - andi. 3,1,8 /* check G-bit */ - bne 4f /* if guarded, take ISI */ - mtctr 0 /* restore counter */ - mfspr 0,IMISS /* get the miss address for the tlbli */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - ori 1,1,0x100 /* set the reference bit */ - mtspr RPA,1 /* set the pte */ - srwi 1,1,8 /* get byte 7 of pte */ - tlbli 0 /* load the itlb */ - stb 1,6(2) /* update page table */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -4: /* guarded */ - mfsrr1 3 - andi. 2,3,0xffff /* clean upper srr1 */ - oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ - b 6f -5: /* not found anywhere */ - mfsrr1 3 - andi. 2,3,0xffff /* clean upper srr1 */ - oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ -6: - mtctr 0 /* restore counter */ - mtsrr1 2 - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_ISI -tlbimsize = .-tlbimiss - - .globl tlbdlmiss,tlbdlmsize -tlbdlmiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,DCMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - mtctr 0 /* restore counter */ - mfspr 0,DMISS /* get the miss address for the tlbld */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - ori 1,1,0x100 /* set the reference bit */ - mtspr RPA,1 /* set the pte */ - srwi 1,1,8 /* get byte 7 of pte */ - tlbld 0 /* load the dtlb */ - stb 1,6(2) /* update page table */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -5: /* not found anywhere */ - mfsrr1 3 - lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ - mtctr 0 /* restore counter */ - andi. 2,3,0xffff /* clean upper srr1 */ - mtsrr1 2 - mtdsisr 1 /* load the dsisr */ - mfspr 1,DMISS /* get the miss address */ - mtdar 1 /* put in dar */ - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_DSI -tlbdlmsize = .-tlbdlmiss - - .globl tlbdsmiss,tlbdsmsize -tlbdsmiss: - mfspr 2,HASH1 /* get first pointer */ - li 1,8 - mfctr 0 /* save counter */ - mfspr 3,DCMP /* get first compare value */ - addi 2,2,-8 /* predec pointer */ -1: - mtctr 1 /* load counter */ -2: - lwzu 1,8(2) /* get next pte */ - cmpl 0,1,3 /* see if found pte */ - bdneq 2b /* loop if not eq */ - bne 3f /* not found */ - lwz 1,4(2) /* load tlb entry lower word */ - andi. 3,1,0x80 /* check the C-bit */ - beq 4f -5: - mtctr 0 /* restore counter */ - mfspr 0,DMISS /* get the miss address for the tlbld */ - mfsrr1 3 /* get the saved cr0 bits */ - mtcrf 0x80,3 /* and restore */ - mtspr RPA,1 /* set the pte */ - tlbld 0 /* load the dtlb */ - rfi - -3: /* not found in pteg */ - andi. 1,3,0x40 /* have we already done second hash? */ - bne 5f - mfspr 2,HASH2 /* get the second pointer */ - ori 3,3,0x40 /* change the compare value */ - li 1,8 - addi 2,2,-8 /* predec pointer */ - b 1b -4: /* found, but C-bit = 0 */ - rlwinm. 3,1,30,0,1 /* test PP */ - bge- 7f - andi. 3,1,1 - beq+ 8f -9: /* found, but protection violation (PP==00)*/ - mfsrr1 3 - lis 1,0xa000000@h /* indicate protection violation - on store */ - b 1f -7: /* found, PP=1x */ - mfspr 3,DMISS /* get the miss address */ - mfsrin 1,3 /* get the segment register */ - mfsrr1 3 - rlwinm 3,3,18,31,31 /* get PR-bit */ - rlwnm. 2,2,3,1,1 /* get the key */ - bne- 9b /* protection violation */ -8: /* found, set reference/change bits */ - lwz 1,4(2) /* reload tlb entry */ - ori 1,1,0x180 - sth 1,6(2) - b 5b -5: /* not found anywhere */ - mfsrr1 3 - lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ - /* dsisr<6> to flag store */ -1: - mtctr 0 /* restore counter */ - andi. 2,3,0xffff /* clean upper srr1 */ - mtsrr1 2 - mtdsisr 1 /* load the dsisr */ - mfspr 1,DMISS /* get the miss address */ - mtdar 1 /* put in dar */ - mfmsr 0 - xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ - mtcrf 0x80,3 /* restore cr0 */ - mtmsr 0 /* now with native gprs */ - isync - ba EXC_DSI -tlbdsmsize = .-tlbdsmiss - -#ifdef DDB -#define ddbsave 0xde0 /* primary save area for DDB */ -/* - * In case of DDB we want a separate trap catcher for it - */ - .local ddbstk - .comm ddbstk,INTSTK,8 /* ddb stack */ - - .globl ddblow,ddbsize -ddblow: - mtsprg 1,1 /* save SP */ - stmw 28,ddbsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - lis 1,ddbstk+INTSTK@ha /* get new SP */ - addi 1,1,ddbstk+INTSTK@l - bla ddbtrap -ddbsize = .-ddblow -#endif /* DDB */ - -#ifdef IPKDB -#define ipkdbsave 0xde0 /* primary save area for IPKDB */ -/* - * In case of IPKDB we want a separate trap catcher for it - */ - - .local ipkdbstk - .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ - - .globl ipkdblow,ipkdbsize -ipkdblow: - mtsprg 1,1 /* save SP */ - stmw 28,ipkdbsave(0) /* free r28-r31 */ - mflr 28 /* save LR */ - mfcr 29 /* save CR */ - lis 1,ipkdbstk+INTSTK@ha /* get new SP */ - addi 1,1,ipkdbstk+INTSTK@l - bla ipkdbtrap -ipkdbsize = .-ipkdblow -#endif /* IPKDB */ - -/* - * FRAME_SETUP assumes: - * SPRG1 SP (1) - * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) - * 28 LR - * 29 CR - * 1 kernel stack - * LR trap type - * SRR0/1 as at start of trap - */ -#define FRAME_SETUP(savearea) \ -/* Have to enable translation to allow access of kernel stack: */ \ - mfsrr0 30; \ - mfsrr1 31; \ - stmw 30,savearea+24(0); \ - mfmsr 30; \ - ori 30,30,(PSL_DR|PSL_IR); \ - mtmsr 30; \ - isync; \ - mfsprg 31,1; \ - stwu 31,-FRAMELEN(1); \ - stw 0,FRAME_0+8(1); \ - stw 31,FRAME_1+8(1); \ - stw 28,FRAME_LR+8(1); \ - stw 29,FRAME_CR+8(1); \ - lmw 28,savearea(0); \ - stmw 2,FRAME_2+8(1); \ - lmw 28,savearea+16(0); \ - mfxer 3; \ - mfctr 4; \ - mflr 5; \ - andi. 5,5,0xff00; \ - stw 3,FRAME_XER+8(1); \ - stw 4,FRAME_CTR+8(1); \ - stw 5,FRAME_EXC+8(1); \ - stw 28,FRAME_DAR+8(1); \ - stw 29,FRAME_DSISR+8(1); \ - stw 30,FRAME_SRR0+8(1); \ - stw 31,FRAME_SRR1+8(1) - -#define FRAME_LEAVE(savearea) \ -/* Now restore regs: */ \ - lwz 2,FRAME_SRR0+8(1); \ - lwz 3,FRAME_SRR1+8(1); \ - lwz 4,FRAME_CTR+8(1); \ - lwz 5,FRAME_XER+8(1); \ - lwz 6,FRAME_LR+8(1); \ - lwz 7,FRAME_CR+8(1); \ - stw 2,savearea(0); \ - stw 3,savearea+4(0); \ - mtctr 4; \ - mtxer 5; \ - mtlr 6; \ - mtsprg 1,7; /* save cr */ \ - lmw 2,FRAME_2+8(1); \ - lwz 0,FRAME_0+8(1); \ - lwz 1,FRAME_1+8(1); \ - mtsprg 2,2; /* save r2 & r3 */ \ - mtsprg 3,3; \ -/* Disable translation, machine check and recoverability: */ \ - mfmsr 2; \ - andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ - mtmsr 2; \ - isync; \ -/* Decide whether we return to user mode: */ \ - lwz 3,savearea+4(0); \ - mtcr 3; \ - bc 4,17,1f; /* branch if PSL_PR is false */ \ -/* Restore user & kernel access SR: */ \ -/* lis 2,curpm@ha; get real address of pmap */ \ -/* lwz 2,curpm@l(2); */ \ -/* lwz 3,PM_USRSR(2); */ \ -/* mtsr USER_SR,3; */ \ -/* lwz 3,PM_KERNELSR(2); */ \ -/* mtsr KERNEL_SR,3; */ \ -1: mfsprg 2,1; /* restore cr */ \ - mtcr 2; \ - lwz 2,savearea(0); \ - lwz 3,savearea+4(0); \ - mtsrr0 2; \ - mtsrr1 3; \ - mfsprg 2,2; /* restore r2 & r3 */ \ - mfsprg 3,3 - -/* - * Preamble code for DSI/ISI traps - */ -disitrap: - lmw 30,disisave(0) - stmw 30,tempsave(0) - lmw 30,disisave+8(0) - stmw 30,tempsave+8(0) - mfdar 30 - mfdsisr 31 - stmw 30,tempsave+16(0) -realtrap: -/* Test whether we already had PR set */ - mfsrr1 1 - mtcr 1 - mfsprg 1,1 /* restore SP (might have been - overwritten) */ - bc 4,17,s_trap /* branch if PSL_PR is false */ - mfsprg 1,0 - lwz 1,PC_CURPCB(1) - addi 1,1,USPACE /* stack is top of user struct */ - -/* - * Now the common trap catching code. - */ -s_trap: -/* First have to enable KERNEL mapping */ - lis 31,KERNEL_SEGMENT@h - ori 31,31,KERNEL_SEGMENT@l - mtsr KERNEL_SR,31 - FRAME_SETUP(tempsave) -/* Now we can recover interrupts again: */ - mfmsr 7 - ori 7,7,(PSL_EE|PSL_FP|PSL_ME|PSL_RI)@l - mtmsr 7 - isync -/* Call C trap code: */ - addi 3,1,8 - mr 30,3 - bl trap - mr 3,30 - bl ast - FRAME_LEAVE(tempsave) - rfi - -/* - * DSI second stage fault handler - */ -s_dsitrap: - mfdsisr 31 /* test whether this may be a - spill fault */ - mtcr 31 - mtsprg 1,1 /* save SP */ - bc 4,1,disitrap /* branch if table miss is false */ - lis 1,spillstk+SPILLSTK@ha - addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ - stwu 1,-52(1) - stw 0,48(1) /* save non-volatile registers */ - stw 3,44(1) - stw 4,40(1) - stw 5,36(1) - stw 6,32(1) - stw 7,28(1) - stw 8,24(1) - stw 9,20(1) - stw 10,16(1) - stw 11,12(1) - stw 12,8(1) - mflr 30 /* save trap type */ - mfctr 31 /* & CTR */ - mfdar 3 -s_pte_spill: - bl pmap_pte_spill /* try a spill */ - or. 3,3,3 - mtctr 31 /* restore CTR */ - mtlr 30 /* and trap type */ - mfsprg 31,2 /* get saved XER */ - mtxer 31 /* restore XER */ - lwz 12,8(1) /* restore non-volatile registers */ - lwz 11,12(1) - lwz 10,16(1) - lwz 9,20(1) - lwz 8,24(1) - lwz 7,28(1) - lwz 6,32(1) - lwz 5,36(1) - lwz 4,40(1) - lwz 3,44(1) - lwz 0,48(1) - beq disitrap - mfsprg 1,1 /* restore SP */ - mtcr 29 /* restore CR */ - mtlr 28 /* restore LR */ - lmw 28,disisave(0) /* restore r28-r31 */ - rfi /* return to trapped code */ - -/* - * ISI second stage fault handler - */ -s_isitrap: - mfsrr1 31 /* test whether this may be a - spill fault */ - mtcr 31 - mtsprg 1,1 /* save SP */ - bc 4,1,disitrap /* branch if table miss is false */ - lis 1,spillstk+SPILLSTK@ha - addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ - stwu 1,-52(1) - stw 0,48(1) /* save non-volatile registers */ - stw 3,44(1) - stw 4,40(1) - stw 5,36(1) - stw 6,32(1) - stw 7,28(1) - stw 8,24(1) - stw 9,20(1) - stw 10,16(1) - stw 11,12(1) - stw 12,8(1) - mfxer 30 /* save XER */ - mtsprg 2,30 - mflr 30 /* save trap type */ - mfctr 31 /* & ctr */ - mfsrr0 3 - b s_pte_spill /* above */ - -/* - * External interrupt second level handler - */ -#define INTRENTER \ -/* Save non-volatile registers: */ \ - stwu 1,-88(1); /* temporarily */ \ - stw 0,84(1); \ - mfsprg 0,1; /* get original SP */ \ - stw 0,0(1); /* and store it */ \ - stw 3,80(1); \ - stw 4,76(1); \ - stw 5,72(1); \ - stw 6,68(1); \ - stw 7,64(1); \ - stw 8,60(1); \ - stw 9,56(1); \ - stw 10,52(1); \ - stw 11,48(1); \ - stw 12,44(1); \ - stw 28,40(1); /* saved LR */ \ - stw 29,36(1); /* saved CR */ \ - stw 30,32(1); /* saved XER */ \ - lmw 28,tempsave(0); /* restore r28-r31 */ \ - mfctr 6; \ - lis 5,intr_depth@ha; \ - lwz 5,intr_depth@l(5); \ - mfsrr0 4; \ - mfsrr1 3; \ - stw 6,28(1); \ - stw 5,20(1); \ - stw 4,12(1); \ - stw 3,8(1); \ -/* interrupts are recoverable here, and enable translation */ \ - lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ - ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ - mtsr KERNEL_SR,3; \ - mfmsr 5; \ - ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ - mtmsr 5; \ - isync - - .globl extint_call -extintr: - INTRENTER -extint_call: - bl extint_call /* to be filled in later */ - -intr_exit: -/* Disable interrupts (should already be disabled) and MMU here: */ - mfmsr 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l - mtmsr 3 - isync -/* restore possibly overwritten registers: */ - lwz 12,44(1) - lwz 11,48(1) - lwz 10,52(1) - lwz 9,56(1) - lwz 8,60(1) - lwz 7,64(1) - lwz 6,8(1) - lwz 5,12(1) - lwz 4,28(1) - lwz 3,32(1) - mtsrr1 6 - mtsrr0 5 - mtctr 4 - mtxer 3 -/* Returning to user mode? */ - mtcr 6 /* saved SRR1 */ - bc 4,17,1f /* branch if PSL_PR is false */ - mfsprg 3,0 /* get pcpu */ - lwz 3,PC_CURPCB(3) /* get curpcb from pcpu */ - lwz 3,PCB_PMR(3) /* get pmap real address from curpcb */ - mtsr KERNEL_SR,3 -/* Setup for entry to realtrap: */ - lwz 3,0(1) /* get saved SP */ - mtsprg 1,3 -#if 0 /* XXX */ - li 6,EXC_AST -#endif - stmw 28,tempsave(0) /* establish tempsave again */ - mtlr 6 - lwz 28,40(1) /* saved LR */ - lwz 29,36(1) /* saved CR */ - lwz 6,68(1) - lwz 5,72(1) - lwz 4,76(1) - lwz 3,80(1) - lwz 0,84(1) - lis 30,intr_depth@ha /* adjust reentrancy count */ - lwz 31,intr_depth@l(30) - addi 31,31,-1 - stw 31,intr_depth@l(30) - b realtrap /* XXX: should call ast(frame ptr) */ -1: -/* Here is the normal exit of extintr: */ - lwz 5,36(1) - lwz 6,40(1) - mtcr 5 - mtlr 6 - lwz 6,68(1) - lwz 5,72(1) - lis 3,intr_depth@ha /* adjust reentrancy count */ - lwz 4,intr_depth@l(3) - addi 4,4,-1 - stw 4,intr_depth@l(3) - lwz 4,76(1) - lwz 3,80(1) - lwz 0,84(1) - lwz 1,0(1) - rfi - -/* - * Decrementer interrupt second level handler - */ -decrintr: - INTRENTER - addi 3,1,8 /* intr frame */ - bl decr_intr - lis 28,decrnest@ha - xor 29,29,29 - stw 29,decrnest@l(28) - b intr_exit - -#ifdef DDB -/* - * Deliberate entry to ddbtrap - */ - .globl ddb_trap -ddb_trap: - mtsprg 1,1 - mfmsr 3 - mtsrr1 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI)@l - mtmsr 3 /* disable interrupts */ - isync - stmw 28,ddbsave(0) - mflr 28 - li 29,EXC_BPT - mtlr 29 - mfcr 29 - mtsrr0 28 - -/* - * Now the ddb trap catching code. - */ -ddbtrap: - FRAME_SETUP(ddbsave) -/* Call C trap code: */ - addi 3,1,8 - bl ddb_trap_glue - or. 3,3,3 - bne ddbleave -/* This wasn't for DDB, so switch to real trap: */ - lwz 3,FRAME_EXC+8(1) /* save exception */ - stw 3,ddbsave+8(0) - FRAME_LEAVE(ddbsave) - mtsprg 1,1 /* prepare for entrance to realtrap */ - stmw 28,tempsave(0) - mflr 28 - mfcr 29 - lwz 31,ddbsave+8(0) - mtlr 31 - b realtrap -ddbleave: - FRAME_LEAVE(ddbsave) - rfi -#endif /* DDB */ - -#ifdef IPKDB -/* - * Deliberate entry to ipkdbtrap - */ - .globl ipkdb_trap -ipkdb_trap: - mtsprg 1,1 - mfmsr 3 - mtsrr1 3 - andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI)@l - mtmsr 3 /* disable interrupts */ - isync - stmw 28,ipkdbsave(0) - mflr 28 - li 29,EXC_BPT - mtlr 29 - mfcr 29 - mtsrr0 28 - -/* - * Now the ipkdb trap catching code. - */ -ipkdbtrap: - FRAME_SETUP(ipkdbsave) -/* Call C trap code: */ - addi 3,1,8 - bl ipkdb_trap_glue - or. 3,3,3 - bne ipkdbleave -/* This wasn't for IPKDB, so switch to real trap: */ - lwz 3,FRAME_EXC+8(1) /* save exception */ - stw 3,ipkdbsave+8(0) - FRAME_LEAVE(ipkdbsave) - mtsprg 1,1 /* prepare for entrance to realtrap */ - stmw 28,tempsave(0) - mflr 28 - mfcr 29 - lwz 31,ipkdbsave+8(0) - mtlr 31 - b realtrap -ipkdbleave: - FRAME_LEAVE(ipkdbsave) - rfi - -ipkdbfault: - ba _ipkdbfault -_ipkdbfault: - mfsrr0 3 - addi 3,3,4 - mtsrr0 3 - li 3,-1 - rfi - -/* - * int ipkdbfbyte(unsigned char *p) - */ - .globl ipkdbfbyte -ipkdbfbyte: - li 9,EXC_DSI /* establish new fault routine */ - lwz 5,0(9) - lis 6,ipkdbfault@ha - lwz 6,ipkdbfault@l(6) - stw 6,0(9) -#ifdef IPKDBUSERHACK - lis 8,ipkdbsr@ha - lwz 8,ipkdbsr@l(8) - mtsr USER_SR,8 - isync -#endif - dcbst 0,9 /* flush data... */ - sync - icbi 0,9 /* and instruction caches */ - lbz 3,0(3) /* fetch data */ - stw 5,0(9) /* restore previous fault handler */ - dcbst 0,9 /* and flush data... */ - sync - icbi 0,9 /* and instruction caches */ - blr - -/* - * int ipkdbsbyte(unsigned char *p, int c) - */ - .globl ipkdbsbyte -ipkdbsbyte: - li 9,EXC_DSI /* establish new fault routine */ - lwz 5,0(9) - lis 6,ipkdbfault@ha - lwz 6,ipkdbfault@l(6) - stw 6,0(9) -#ifdef IPKDBUSERHACK - lis 8,ipkdbsr@ha - lwz 8,ipkdbsr@l(8) - mtsr USER_SR,8 - isync -#endif - dcbst 0,9 /* flush data... */ - sync - icbi 0,9 /* and instruction caches */ - mr 6,3 - xor 3,3,3 - stb 4,0(6) - dcbst 0,6 /* Now do appropriate flushes - to data... */ - sync - icbi 0,6 /* and instruction caches */ - stw 5,0(9) /* restore previous fault handler */ - dcbst 0,9 /* and flush data... */ - sync - icbi 0,9 /* and instruction caches */ - blr -#endif /* IPKDB */ - -/* * int setfault() * * Similar to setjmp to setup for handling faults on accesses to user memory. @@ -1326,7 +407,8 @@ setfault: mflr 0 mfcr 12 mfsprg 4,0 - lwz 4,PC_CURPCB(4) + lwz 4,PC_CURTHREAD(4) + lwz 4,TD_PCB(4) stw 3,PCB_ONFAULT(4) stw 0,0(3) stw 1,4(3) @@ -1335,15 +417,4 @@ setfault: xor 3,3,3 blr -/* - * Signal "trampoline" code. - */ - .globl sigcode -sigcode: - b sys_exit -esigcode: - .data -GLOBAL(szsigcode) - .long esigcode-sigcode - .text - +#include <powerpc/powerpc/trap_subr.S> diff --git a/sys/powerpc/powerpc/sigcode.S b/sys/powerpc/powerpc/sigcode.S new file mode 100644 index 0000000..fcc1aa5 --- /dev/null +++ b/sys/powerpc/powerpc/sigcode.S @@ -0,0 +1,54 @@ +/* $FreeBSD$ */ +/* $NetBSD: sigcode.S,v 1.1 1999/11/17 14:56:11 kleink Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <machine/asm.h> +#include <sys/syscall.h> + +/* + * The following code gets copied to the top of the user stack on process + * execution. It does signal trampolining on signal delivery. + * + * On entry r1 points to a struct sigframe at bottom of current stack. + * All other registers are unchanged. + */ + .globl _C_LABEL(sigcode),_C_LABEL(szsigcode) +_C_LABEL(sigcode): + addi 1,1,-16 /* reserved space for callee */ + blrl + addi 3,1,16+8 /* compute &sf_sc */ + li 0,SYS_sigreturn + sc /* sigreturn(scp) */ + li 0,SYS_exit + sc /* exit(errno) */ +_C_LABEL(szsigcode) = . - _C_LABEL(sigcode) diff --git a/sys/powerpc/powerpc/swtch.S b/sys/powerpc/powerpc/swtch.S index afa1ba5..875328e 100644 --- a/sys/powerpc/powerpc/swtch.S +++ b/sys/powerpc/powerpc/swtch.S @@ -106,17 +106,29 @@ ENTRY(cpu_switch) mfsprg %r4,0 /* Get the pcpu pointer */ stw %r16,PC_CURTHREAD(%r4) /* Store new current thread */ - lwz %r4,TD_PCB(%r16) /* Grab the new PCB */ + lwz %r15,TD_PROC(%r16) /* Grab the current thread's proc */ + lwz %r15,P_VMSPACE(%r15) /* Grab the current proc's vmspace */ + lwz %r15,VM_PMAP(%r15) /* ... pmap */ + mr %r3,%r15 + bl pmap_kextract + cmpwi cr4,%r3,0 + bne cr4,.L2 + mr %r3,%r15 +.L2: + stw %r3,PC_CURPMAP(%r4) /* Store it */ + lwz %r16,TD_PCB(%r16) /* Grab the new PCB */ + stw %r16,PC_CURPCB(%r4) + mr %r4,%r16 #if 0 lwz %r29, PCB_FLAGS(%r4) /* Restore FPU regs if needed */ andi. %r9, %r29, 1 - beq .L2 + beq .L3 mr %r3, %r4 bl enable_fpu #endif -.L2: +.L3: lmw %r14,PCB_CONTEXT(%r4) /* Load the non-volatile GP regs */ lwz %r5,PCB_CR(%r4) /* Load the condition register */ mtcr %r5 @@ -140,8 +152,9 @@ ENTRY(savectx) * Set up the return from cpu_fork() */ ENTRY(fork_trampoline) - lwz %r3,CF_FUNC(1) - lwz %r4,CF_ARG0(1) - lwz %r5,CF_ARG1(1) + lwz %r3,CF_FUNC(%r1) + lwz %r4,CF_ARG0(%r1) + lwz %r5,CF_ARG1(%r1) bl fork_exit - rfi + addi %r1,%r1,4 + b trapexit diff --git a/sys/powerpc/powerpc/swtch.s b/sys/powerpc/powerpc/swtch.s index afa1ba5..875328e 100644 --- a/sys/powerpc/powerpc/swtch.s +++ b/sys/powerpc/powerpc/swtch.s @@ -106,17 +106,29 @@ ENTRY(cpu_switch) mfsprg %r4,0 /* Get the pcpu pointer */ stw %r16,PC_CURTHREAD(%r4) /* Store new current thread */ - lwz %r4,TD_PCB(%r16) /* Grab the new PCB */ + lwz %r15,TD_PROC(%r16) /* Grab the current thread's proc */ + lwz %r15,P_VMSPACE(%r15) /* Grab the current proc's vmspace */ + lwz %r15,VM_PMAP(%r15) /* ... pmap */ + mr %r3,%r15 + bl pmap_kextract + cmpwi cr4,%r3,0 + bne cr4,.L2 + mr %r3,%r15 +.L2: + stw %r3,PC_CURPMAP(%r4) /* Store it */ + lwz %r16,TD_PCB(%r16) /* Grab the new PCB */ + stw %r16,PC_CURPCB(%r4) + mr %r4,%r16 #if 0 lwz %r29, PCB_FLAGS(%r4) /* Restore FPU regs if needed */ andi. %r9, %r29, 1 - beq .L2 + beq .L3 mr %r3, %r4 bl enable_fpu #endif -.L2: +.L3: lmw %r14,PCB_CONTEXT(%r4) /* Load the non-volatile GP regs */ lwz %r5,PCB_CR(%r4) /* Load the condition register */ mtcr %r5 @@ -140,8 +152,9 @@ ENTRY(savectx) * Set up the return from cpu_fork() */ ENTRY(fork_trampoline) - lwz %r3,CF_FUNC(1) - lwz %r4,CF_ARG0(1) - lwz %r5,CF_ARG1(1) + lwz %r3,CF_FUNC(%r1) + lwz %r4,CF_ARG0(%r1) + lwz %r5,CF_ARG1(%r1) bl fork_exit - rfi + addi %r1,%r1,4 + b trapexit diff --git a/sys/powerpc/powerpc/trap_subr.S b/sys/powerpc/powerpc/trap_subr.S new file mode 100644 index 0000000..f348768 --- /dev/null +++ b/sys/powerpc/powerpc/trap_subr.S @@ -0,0 +1,1128 @@ +/* $FreeBSD$ */ +/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NOTICE: This is not a standalone file. to use it, #include it in + * your port's locore.S, like so: + * + * #include <powerpc/powerpc/trap_subr.S> + */ + +/* + * XXX Fake AST trap vector. This is here until we work out how to safely + * remove the AST code. + */ +#define EXC_AST 0x3000 + .data + .align 4 +astpending: + .long 0 + +/* + * Data used during primary/secondary traps/interrupts + */ +#define tempsave EXC_MCHK+0xe0 /* primary save area for trap handling */ +#define disisave EXC_DSI+0xe0 /* primary save area for dsi/isi traps */ + +/* + * XXX Interrupt and spill stacks need to be per-CPU. + */ + .data + .align 4 +intstk: + .space INTSTK /* interrupt stack */ + +GLOBAL(intr_depth) + .long -1 /* in-use marker */ + + .comm spillstk,SPILLSTK,8 + +/* + * This code gets copied to all the trap vectors + * (except ISI/DSI, ALI, the interrupts, and possibly the debugging + * traps when using IPKDB). + */ + .text + .globl _C_LABEL(trapcode),_C_LABEL(trapsize) +_C_LABEL(trapcode): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ +/* Test whether we already had PR set */ + mfsrr1 31 + mtcr 31 + bc 4,17,1f /* branch if PSL_PR is clear */ + mfsprg 31,0 + lwz 1,PC_CURPCB(31) + addi 1,1,USPACE /* stack is top of user struct */ +1: + bla s_trap +_C_LABEL(trapsize) = .-_C_LABEL(trapcode) + +/* + * For ALI: has to save DSISR and DAR + */ + .globl _C_LABEL(alitrap),_C_LABEL(alisize) +_C_LABEL(alitrap): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mfdar 30 + mfdsisr 31 + stmw 30,tempsave+16(0) + mflr 28 /* save LR */ + mfcr 29 /* save CR */ +/* Test whether we already had PR set */ + mfsrr1 31 + mtcr 31 + bc 4,17,1f /* branch if PSL_PR is clear */ + mfsprg 31,0 + lwz 1,PC_CURPCB(31) + addi 1,1,USPACE /* stack is top of user struct */ +1: + bla s_trap +_C_LABEL(alisize) = .-_C_LABEL(alitrap) + +/* + * Similar to the above for DSI + * Has to handle BAT spills + * and standard pagetable spills + */ + .globl _C_LABEL(dsitrap),_C_LABEL(dsisize) +_C_LABEL(dsitrap): + stmw 28,disisave(0) /* free r28-r31 */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + mtsprg 2,30 /* in SPRG2 */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfdar 31 /* get fault address */ + rlwinm 31,31,7,25,28 /* get segment * 8 */ + + /* get batu */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)@l(31) + mtcr 30 + bc 4,30,1f /* branch if supervisor valid is + false */ + /* get batl */ + lwz 31,_C_LABEL(battable)+4@l(31) +/* We randomly use the highest two bat registers here */ + mftb 28 + andi. 28,28,1 + bne 2f + mtdbatu 2,30 + mtdbatl 2,31 + b 3f +2: + mtdbatu 3,30 + mtdbatl 3,31 +3: + mfsprg 30,2 /* restore XER */ + mtxer 30 + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + mflr 28 /* save LR */ + bla s_dsitrap +_C_LABEL(dsisize) = .-_C_LABEL(dsitrap) + +/* + * Dedicated MPC601 version of the above. + * Considers different BAT format and combined implementation + * (being addressed as I-BAT). + */ + .globl _C_LABEL(dsitrap601),_C_LABEL(dsi601size) +_C_LABEL(dsitrap601): + stmw 28,disisave(0) /* free r28-r31 */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + mtsprg 2,30 /* in SPRG2 */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfdar 31 /* get fault address */ + rlwinm 31,31,12,20,28 /* get "segment" battable offset */ + + /* get batl */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)+4@l(31) + mtcr 30 + bc 4,25,1f /* branch if Valid is is false, + presently assumes supervisor only */ + + /* get batu */ + lwz 31,_C_LABEL(battable)@l(31) +/* We randomly use the highest two bat registers here */ + mfspr 28,SPR_RTCL_R + andi. 28,28,128 + bne 2f + mtibatu 2,31 + mtibatl 2,30 + b 3f +2: + mtibatu 3,31 + mtibatl 3,30 +3: + mfsprg 30,2 /* restore XER */ + mtxer 30 + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + mflr 28 /* save LR */ + bla s_dsitrap +_C_LABEL(dsi601size) = .-_C_LABEL(dsitrap601) + +/* + * Similar to the above for ISI + */ + .globl _C_LABEL(isitrap),_C_LABEL(isisize) +_C_LABEL(isitrap): + stmw 28,disisave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfsrr0 31 /* get fault address */ + rlwinm 31,31,7,25,28 /* get segment * 8 */ + + /* get batu */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)@l(31) + mtcr 30 + bc 4,30,1f /* branch if supervisor valid is + false */ + mtibatu 3,30 + + /* get batl */ + lwz 30,_C_LABEL(battable)+4@l(31) + mtibatl 3,30 + + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + bla s_isitrap +_C_LABEL(isisize)= .-_C_LABEL(isitrap) + +/* + * Dedicated MPC601 version of the above. + * Considers different BAT format. + */ + .globl _C_LABEL(isitrap601),_C_LABEL(isi601size) +_C_LABEL(isitrap601): + stmw 28,disisave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfsrr1 31 /* test kernel mode */ + mtcr 31 + bc 12,17,1f /* branch if PSL_PR is set */ + mfsrr0 31 /* get fault address */ + rlwinm 31,31,12,20,28 /* get "segment" battable offset */ + + /* get batl */ + addis 31,31,_C_LABEL(battable)@ha + lwz 30,_C_LABEL(battable)+4@l(31) + mtcr 30 + bc 4,25,1f /* branch if Valid is is false, + presently assumes supervisor only */ + /* get batu */ + lwz 31,_C_LABEL(battable)@l(31) + + mtibatu 3,31 + mtibatl 3,30 + + mtcr 29 /* restore CR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ +1: + bla s_isitrap +_C_LABEL(isi601size)= .-_C_LABEL(isitrap601) + +/* + * This one for the external interrupt handler. + */ + .globl _C_LABEL(extint),_C_LABEL(extsize) +_C_LABEL(extint): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + lis 1,intstk+INTSTK@ha /* get interrupt stack */ + addi 1,1,intstk+INTSTK@l /* this is really intr_depth! */ + lwz 31,0(1) /* were we already running on intstk? */ + addic. 31,31,1 + stw 31,0(1) + beq 1f + mfsprg 1,1 /* yes, get old SP */ +1: + ba extintr +_C_LABEL(extsize) = .-_C_LABEL(extint) + +/* + * And this one for the decrementer interrupt handler. + */ + .globl _C_LABEL(decrint),_C_LABEL(decrsize) +_C_LABEL(decrint): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + mfxer 30 /* save XER */ + lis 1,intstk+INTSTK@ha /* get interrupt stack */ + addi 1,1,intstk+INTSTK@l + lwz 31,0(1) /* were we already running on intstk? */ + addic. 31,31,1 + stw 31,0(1) + beq 1f + mfsprg 1,1 /* yes, get old SP */ +1: + ba decrintr +_C_LABEL(decrsize) = .-_C_LABEL(decrint) + +/* + * Now the tlb software load for 603 processors: + * (Code essentially from the 603e User Manual, Chapter 5, but + * corrected a lot.) + */ + + .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize) +_C_LABEL(tlbimiss): +#ifdef PMAPDEBUG + mfspr 2,SPR_IMISS /* exception address */ + li 1,24 /* get rid of the lower */ + srw 2,2,1 /* 24 bits */ + li 1,1 /* Load 1 */ + cmpl 2,1,1 /* is it > 16MB */ + blt 99f /* nope, skip saving these SPRs */ + li 1,0xc0 /* arbitrary */ + mfspr 2,SPR_HASH1 + stw 2,0(1) + mfspr 2,SPR_HASH2 + stw 2,4(1) + mfspr 2,SPR_IMISS + stw 2,8(1) + mfspr 2,SPR_ICMP + stw 2,12(1) +99: +#endif /* PMAPDEBUG */ + mfspr 2,SPR_HASH1 /* get first pointer */ + li 1,8 + mfctr 0 /* save counter */ + mfspr 3,SPR_ICMP /* get first compare value */ + addi 2,2,-8 /* predec pointer */ +1: + mtctr 1 /* load counter */ +2: + lwzu 1,8(2) /* get next pte */ + cmpl 0,1,3 /* see if found pte */ + bdneq 2b /* loop if not eq */ + bne 3f /* not found */ + lwz 1,4(2) /* load tlb entry lower word */ + andi. 3,1,8 /* check G-bit */ + bne 4f /* if guarded, take ISI */ + mtctr 0 /* restore counter */ + mfspr 0,SPR_IMISS /* get the miss address for the tlbli */ + mfsrr1 3 /* get the saved cr0 bits */ + mtcrf 0x80,3 /* and restore */ + ori 1,1,0x100 /* set the reference bit */ + mtspr SPR_RPA,1 /* set the pte */ + srwi 1,1,8 /* get byte 7 of pte */ + tlbli 0 /* load the itlb */ + stb 1,6(2) /* update page table */ + rfi + +3: /* not found in pteg */ + andi. 1,3,0x40 /* have we already done second hash? */ + bne 5f + mfspr 2,SPR_HASH2 /* get the second pointer */ + ori 3,3,0x40 /* change the compare value */ + li 1,8 + addi 2,2,-8 /* predec pointer */ + b 1b +4: /* guarded */ + mfsrr1 3 + andi. 2,3,0xffff /* clean upper srr1 */ + oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ + b 6f +5: /* not found anywhere */ + mfsrr1 3 + andi. 2,3,0xffff /* clean upper srr1 */ + oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ +6: + mtctr 0 /* restore counter */ + mtsrr1 2 + mfmsr 0 + xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,3 /* restore cr0 */ + mtmsr 0 /* now with native gprs */ + isync + ba EXC_ISI +_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss) + + .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize) +_C_LABEL(tlbdlmiss): + mfspr 2,SPR_HASH1 /* get first pointer */ + li 1,8 + mfctr 0 /* save counter */ + mfspr 3,SPR_DCMP /* get first compare value */ + addi 2,2,-8 /* predec pointer */ +1: + mtctr 1 /* load counter */ +2: + lwzu 1,8(2) /* get next pte */ + cmpl 0,1,3 /* see if found pte */ + bdneq 2b /* loop if not eq */ + bne 3f /* not found */ + lwz 1,4(2) /* load tlb entry lower word */ + mtctr 0 /* restore counter */ + mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ + mfsrr1 3 /* get the saved cr0 bits */ + mtcrf 0x80,3 /* and restore */ + ori 1,1,0x100 /* set the reference bit */ + mtspr SPR_RPA,1 /* set the pte */ + srwi 1,1,8 /* get byte 7 of pte */ + tlbld 0 /* load the dtlb */ + stb 1,6(2) /* update page table */ + rfi + +3: /* not found in pteg */ + andi. 1,3,0x40 /* have we already done second hash? */ + bne 5f + mfspr 2,SPR_HASH2 /* get the second pointer */ + ori 3,3,0x40 /* change the compare value */ + li 1,8 + addi 2,2,-8 /* predec pointer */ + b 1b +5: /* not found anywhere */ + mfsrr1 3 + lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ + mtctr 0 /* restore counter */ + andi. 2,3,0xffff /* clean upper srr1 */ + mtsrr1 2 + mtdsisr 1 /* load the dsisr */ + mfspr 1,SPR_DMISS /* get the miss address */ + mtdar 1 /* put in dar */ + mfmsr 0 + xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,3 /* restore cr0 */ + mtmsr 0 /* now with native gprs */ + isync + ba EXC_DSI +_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss) + + .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize) +_C_LABEL(tlbdsmiss): + mfspr 2,SPR_HASH1 /* get first pointer */ + li 1,8 + mfctr 0 /* save counter */ + mfspr 3,SPR_DCMP /* get first compare value */ + addi 2,2,-8 /* predec pointer */ +1: + mtctr 1 /* load counter */ +2: + lwzu 1,8(2) /* get next pte */ + cmpl 0,1,3 /* see if found pte */ + bdneq 2b /* loop if not eq */ + bne 3f /* not found */ + lwz 1,4(2) /* load tlb entry lower word */ + andi. 3,1,0x80 /* check the C-bit */ + beq 4f +5: + mtctr 0 /* restore counter */ + mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ + mfsrr1 3 /* get the saved cr0 bits */ + mtcrf 0x80,3 /* and restore */ + mtspr SPR_RPA,1 /* set the pte */ + tlbld 0 /* load the dtlb */ + rfi + +3: /* not found in pteg */ + andi. 1,3,0x40 /* have we already done second hash? */ + bne 5f + mfspr 2,SPR_HASH2 /* get the second pointer */ + ori 3,3,0x40 /* change the compare value */ + li 1,8 + addi 2,2,-8 /* predec pointer */ + b 1b +4: /* found, but C-bit = 0 */ + rlwinm. 3,1,30,0,1 /* test PP */ + bge- 7f + andi. 3,1,1 + beq+ 8f +9: /* found, but protection violation (PP==00)*/ + mfsrr1 3 + lis 1,0xa000000@h /* indicate protection violation + on store */ + b 1f +7: /* found, PP=1x */ + mfspr 3,SPR_DMISS /* get the miss address */ + mfsrin 1,3 /* get the segment register */ + mfsrr1 3 + rlwinm 3,3,18,31,31 /* get PR-bit */ + rlwnm. 2,2,3,1,1 /* get the key */ + bne- 9b /* protection violation */ +8: /* found, set reference/change bits */ + lwz 1,4(2) /* reload tlb entry */ + ori 1,1,0x180 + sth 1,6(2) + b 5b +5: /* not found anywhere */ + mfsrr1 3 + lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ + /* dsisr<6> to flag store */ +1: + mtctr 0 /* restore counter */ + andi. 2,3,0xffff /* clean upper srr1 */ + mtsrr1 2 + mtdsisr 1 /* load the dsisr */ + mfspr 1,SPR_DMISS /* get the miss address */ + mtdar 1 /* put in dar */ + mfmsr 0 + xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,3 /* restore cr0 */ + mtmsr 0 /* now with native gprs */ + isync + ba EXC_DSI +_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss) + +#if defined(DDB) || defined(KGDB) +#define ddbsave 0xde0 /* primary save area for DDB */ +/* + * In case of DDB we want a separate trap catcher for it + */ + .local ddbstk + .comm ddbstk,INTSTK,8 /* ddb stack */ + + .globl _C_LABEL(ddblow),_C_LABEL(ddbsize) +_C_LABEL(ddblow): + mtsprg 1,1 /* save SP */ + stmw 28,ddbsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + lis 1,ddbstk+INTSTK@ha /* get new SP */ + addi 1,1,ddbstk+INTSTK@l + bla ddbtrap +_C_LABEL(ddbsize) = .-_C_LABEL(ddblow) +#endif /* DDB | KGDB */ + +#ifdef IPKDB +#define ipkdbsave 0xde0 /* primary save area for IPKDB */ +/* + * In case of IPKDB we want a separate trap catcher for it + */ + + .local ipkdbstk + .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ + + .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize) +_C_LABEL(ipkdblow): + mtsprg 1,1 /* save SP */ + stmw 28,ipkdbsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + lis 1,ipkdbstk+INTSTK@ha /* get new SP */ + addi 1,1,ipkdbstk+INTSTK@l + bla ipkdbtrap +_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow) +#endif /* IPKDB */ + +/* + * FRAME_SETUP assumes: + * SPRG1 SP (1) + * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) + * 28 LR + * 29 CR + * 1 kernel stack + * LR trap type + * SRR0/1 as at start of trap + */ +#define FRAME_SETUP(savearea) \ +/* Have to enable translation to allow access of kernel stack: */ \ + mfsrr0 30; \ + mfsrr1 31; \ + stmw 30,savearea+24(0); \ + mfmsr 30; \ + ori 30,30,(PSL_DR|PSL_IR); \ + mtmsr 30; \ + isync; \ + mfsprg 31,1; \ + stwu 31,-FRAMELEN(1); \ + stw 0,FRAME_0+8(1); \ + stw 31,FRAME_1+8(1); \ + stw 28,FRAME_LR+8(1); \ + stw 29,FRAME_CR+8(1); \ + lmw 28,savearea(0); \ + stmw 2,FRAME_2+8(1); \ + lmw 28,savearea+16(0); \ + mfxer 3; \ + mfctr 4; \ + mflr 5; \ + andi. 5,5,0xff00; \ + stw 3,FRAME_XER+8(1); \ + stw 4,FRAME_CTR+8(1); \ + stw 5,FRAME_EXC+8(1); \ + stw 28,FRAME_DAR+8(1); \ + stw 29,FRAME_DSISR+8(1); \ + stw 30,FRAME_SRR0+8(1); \ + stw 31,FRAME_SRR1+8(1) + +#define FRAME_LEAVE(savearea) \ +/* Now restore regs: */ \ + lwz 2,FRAME_SRR0+8(1); \ + lwz 3,FRAME_SRR1+8(1); \ + lwz 4,FRAME_CTR+8(1); \ + lwz 5,FRAME_XER+8(1); \ + lwz 6,FRAME_LR+8(1); \ + lwz 7,FRAME_CR+8(1); \ + stw 2,savearea(0); \ + stw 3,savearea+4(0); \ + mtctr 4; \ + mtxer 5; \ + mtlr 6; \ + mtsprg 1,7; /* save cr */ \ + lmw 2,FRAME_2+8(1); \ + lwz 0,FRAME_0+8(1); \ + lwz 1,FRAME_1+8(1); \ + mtsprg 2,2; /* save r2 & r3 */ \ + mtsprg 3,3; \ +/* Disable translation, machine check and recoverability: */ \ + mfmsr 2; \ + andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ + mtmsr 2; \ + isync; \ +/* Decide whether we return to user mode: */ \ + lwz 3,savearea+4(0); \ + mtcr 3; \ + bc 4,17,1f; /* branch if PSL_PR is false */ \ +/* Restore user & kernel access SR: */ \ + mfsprg 2,0; \ + lwz 2,PC_CURPMAP(2); \ + lwz 3,PM_SR+0(2); \ + mtsr 0,3; /* restore SR0 */ \ + lwz 3,PM_SR+4(2); \ + mtsr 1,3; /* restore SR1 */ \ + lwz 3,PM_SR+8(2); \ + mtsr 2,3; /* restore SR2 */ \ + lwz 3,PM_SR+12(2); \ + mtsr 3,3; /* restore SR3 */ \ + lwz 3,PM_SR+16(2); \ + mtsr 4,3; /* restore SR4 */ \ + lwz 3,PM_SR+20(2); \ + mtsr 5,3; /* restore SR5 */ \ + lwz 3,PM_SR+24(2); \ + mtsr 6,3; /* restore SR6 */ \ + lwz 3,PM_SR+28(2); \ + mtsr 7,3; /* restore SR7 */ \ + lwz 3,PM_USRSR(2); \ + mtsr USER_SR,3; \ + lwz 3,PM_KERNELSR(2); \ + mtsr KERNEL_SR,3; \ +1: mfsprg 2,1; /* restore cr */ \ + mtcr 2; \ + lwz 2,savearea(0); \ + lwz 3,savearea+4(0); \ + mtsrr0 2; \ + mtsrr1 3; \ + mfsprg 2,2; /* restore r2 & r3 */ \ + mfsprg 3,3 + +/* + * Preamble code for DSI/ISI traps + */ +disitrap: + lmw 30,disisave(0) + stmw 30,tempsave(0) + lmw 30,disisave+8(0) + stmw 30,tempsave+8(0) + mfdar 30 + mfdsisr 31 + stmw 30,tempsave+16(0) +realtrap: +/* Test whether we already had PR set */ + mfsrr1 1 + mtcr 1 + mfsprg 1,1 /* restore SP (might have been + overwritten) */ + bc 4,17,s_trap /* branch if PSL_PR is false */ + mfsprg 31,0 + lwz 1,PC_CURPCB(31) + addi 1,1,USPACE /* stack is top of user struct */ + +/* + * Now the common trap catching code. + */ +s_trap: +/* First have to enable KERNEL mapping */ + lis 31,KERNEL_SEGMENT@h + ori 31,31,KERNEL_SEGMENT@l + mtsr KERNEL_SR,31 +/* Obliterate SRs so BAT spills work correctly */ + lis 31,EMPTY_SEGMENT@h + ori 31,31,EMPTY_SEGMENT@l + mtsr 0,31 + mtsr 1,31 + mtsr 2,31 + mtsr 3,31 + mtsr 4,31 + mtsr 5,31 + mtsr 6,31 + mtsr 7,31 + FRAME_SETUP(tempsave) +/* Now we can recover interrupts again: */ + mfmsr 7 + ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l + mtmsr 7 + isync +/* Call C trap code: */ +trapagain: + addi 3,1,8 + bl _C_LABEL(trap) + .globl _C_LABEL(trapexit) +_C_LABEL(trapexit): +/* Disable interrupts: */ + mfmsr 3 + andi. 3,3,~PSL_EE@l + mtmsr 3 +/* Test AST pending: */ + lwz 5,FRAME_SRR1+8(1) + mtcr 5 + bc 4,17,1f /* branch if PSL_PR is false */ + lis 3,_C_LABEL(astpending)@ha + lwz 4,_C_LABEL(astpending)@l(3) + andi. 4,4,1 + beq 1f + li 6,EXC_AST + stw 6,FRAME_EXC+8(1) + b trapagain +1: + FRAME_LEAVE(tempsave) + rfi + +/* + * DSI second stage fault handler + */ +s_dsitrap: + mfdsisr 31 /* test whether this may be a + spill fault */ + mtcr 31 + mtsprg 1,1 /* save SP */ + bc 4,1,disitrap /* branch if table miss is false */ + lis 1,spillstk+SPILLSTK@ha + addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ + stwu 1,-SPFRAMELEN(1) + stw 0,SPFRAME_R0(1) /* save non-volatile registers */ + stw 3,SPFRAME_R3(1) + stw 4,SPFRAME_R4(1) + stw 5,SPFRAME_R5(1) + stw 6,SPFRAME_R6(1) + stw 7,SPFRAME_R7(1) + stw 8,SPFRAME_R8(1) + stw 9,SPFRAME_R9(1) + stw 10,SPFRAME_R10(1) + stw 11,SPFRAME_R11(1) + stw 12,SPFRAME_R12(1) + mflr 30 /* save trap type */ + mfctr 31 /* & CTR */ + mfdar 3 +s_pte_spill: + bl _C_LABEL(pmap_pte_spill) /* try a spill */ + or. 3,3,3 + mtctr 31 /* restore CTR */ + mtlr 30 /* and trap type */ + mfsprg 31,2 /* get saved XER */ + mtxer 31 /* restore XER */ + lwz 12,SPFRAME_R12(1) /* restore non-volatile registers */ + lwz 11,SPFRAME_R11(1) + lwz 10,SPFRAME_R10(1) + lwz 9,SPFRAME_R9(1) + lwz 8,SPFRAME_R8(1) + lwz 7,SPFRAME_R7(1) + lwz 6,SPFRAME_R6(1) + lwz 5,SPFRAME_R5(1) + lwz 4,SPFRAME_R4(1) + lwz 3,SPFRAME_R3(1) + lwz 0,SPFRAME_R0(1) + beq disitrap + mfsprg 1,1 /* restore SP */ + mtcr 29 /* restore CR */ + mtlr 28 /* restore LR */ + lmw 28,disisave(0) /* restore r28-r31 */ + rfi /* return to trapped code */ + +/* + * ISI second stage fault handler + */ +s_isitrap: + mfsrr1 31 /* test whether this may be a + spill fault */ + mtcr 31 + mtsprg 1,1 /* save SP */ + bc 4,1,disitrap /* branch if table miss is false */ + lis 1,spillstk+SPILLSTK@ha + addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ + stwu 1,-SPFRAMELEN(1) + stw 0,SPFRAME_R0(1) /* save non-volatile registers */ + stw 3,SPFRAME_R3(1) + stw 4,SPFRAME_R4(1) + stw 5,SPFRAME_R5(1) + stw 6,SPFRAME_R6(1) + stw 7,SPFRAME_R7(1) + stw 8,SPFRAME_R8(1) + stw 9,SPFRAME_R9(1) + stw 10,SPFRAME_R10(1) + stw 11,SPFRAME_R11(1) + stw 12,SPFRAME_R12(1) + mfxer 30 /* save XER */ + mtsprg 2,30 + mflr 30 /* save trap type */ + mfctr 31 /* & ctr */ + mfsrr0 3 + b s_pte_spill /* above */ + +/* + * External interrupt second level handler + */ +#define INTRENTER \ +/* Save non-volatile registers: */ \ + stwu 1,-IFRAMELEN(1); /* temporarily */ \ + stw 0,IFRAME_R0(1); \ + mfsprg 0,1; /* get original SP */ \ + stw 0,IFRAME_R1(1); /* and store it */ \ + stw 3,IFRAME_R3(1); \ + stw 4,IFRAME_R4(1); \ + stw 5,IFRAME_R5(1); \ + stw 6,IFRAME_R6(1); \ + stw 7,IFRAME_R7(1); \ + stw 8,IFRAME_R8(1); \ + stw 9,IFRAME_R9(1); \ + stw 10,IFRAME_R10(1); \ + stw 11,IFRAME_R11(1); \ + stw 12,IFRAME_R12(1); \ + stw 28,IFRAME_LR(1); /* saved LR */ \ + stw 29,IFRAME_CR(1); /* saved CR */ \ + stw 30,IFRAME_XER(1); /* saved XER */ \ + lmw 28,tempsave(0); /* restore r28-r31 */ \ + mfctr 6; \ + lis 5,_C_LABEL(intr_depth)@ha; \ + lwz 5,_C_LABEL(intr_depth)@l(5); \ + mfsrr0 4; \ + mfsrr1 3; \ + stw 6,IFRAME_CTR(1); \ + stw 5,IFRAME_INTR_DEPTH(1); \ + stw 4,IFRAME_SRR0(1); \ + stw 3,IFRAME_SRR1(1); \ + mtcr 3; \ + bc 4,17,99f; /* branch if PSL_PR is false */ \ + lis 3,EMPTY_SEGMENT@h; \ + ori 3,3,EMPTY_SEGMENT@l; \ + mtsr 0,3; /* reset SRs so BAT spills work */ \ + mtsr 1,3; \ + mtsr 2,3; \ + mtsr 3,3; \ + mtsr 4,3; \ + mtsr 5,3; \ + mtsr 6,3; \ + mtsr 7,3; \ +/* interrupts are recoverable here, and enable translation */ \ + lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ + ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ + mtsr KERNEL_SR,3; \ +99: mfmsr 5; \ + ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ + mtmsr 5; \ + isync + + .globl _C_LABEL(extint_call) +extintr: + INTRENTER +_C_LABEL(extint_call): + bl _C_LABEL(extint_call) /* to be filled in later */ + +intr_exit: +/* Disable interrupts (should already be disabled) and MMU here: */ + mfmsr 3 + andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l + mtmsr 3 + isync +/* restore possibly overwritten registers: */ + lwz 12,IFRAME_R12(1) + lwz 11,IFRAME_R11(1) + lwz 10,IFRAME_R10(1) + lwz 9,IFRAME_R9(1) + lwz 8,IFRAME_R8(1) + lwz 7,IFRAME_R7(1) + lwz 6,IFRAME_SRR1(1) + lwz 5,IFRAME_SRR0(1) + lwz 4,IFRAME_CTR(1) + lwz 3,IFRAME_XER(1) + mtsrr1 6 + mtsrr0 5 + mtctr 4 + mtxer 3 +/* Returning to user mode? */ + mtcr 6 /* saved SRR1 */ + bc 4,17,1f /* branch if PSL_PR is false */ + mfsprg 31,0 + lwz 3,PC_CURPMAP(31) + lwz 4,PM_SR+0(3) + mtsr 0,4 /* Restore SR0 */ + lwz 4,PM_SR+4(3) + mtsr 1,4 /* Restore SR1 */ + lwz 4,PM_SR+8(3) + mtsr 2,4 /* Restore SR2 */ + lwz 4,PM_SR+12(3) + mtsr 3,4 /* Restore SR3 */ + lwz 4,PM_SR+16(3) + mtsr 4,4 /* Restore SR4 */ + lwz 4,PM_SR+20(3) + mtsr 5,4 /* Restore SR5 */ + lwz 4,PM_SR+24(3) + mtsr 6,4 /* Restore SR6 */ + lwz 4,PM_SR+28(3) + mtsr 7,4 /* Restore SR7 */ + lwz 3,PM_KERNELSR(3) + mtsr KERNEL_SR,3 /* Restore kernel SR */ + lis 3,_C_LABEL(astpending)@ha /* Test AST pending */ + lwz 4,_C_LABEL(astpending)@l(3) + andi. 4,4,1 + beq 1f +/* Setup for entry to realtrap: */ + lwz 3,IFRAME_R1(1) /* get saved SP */ + mtsprg 1,3 + li 6,EXC_AST + stmw 28,tempsave(0) /* establish tempsave again */ + mtlr 6 + lwz 28,IFRAME_LR(1) /* saved LR */ + lwz 29,IFRAME_CR(1) /* saved CR */ + lwz 6,IFRAME_R6(1) + lwz 5,IFRAME_R5(1) + lwz 4,IFRAME_R4(1) + lwz 3,IFRAME_R3(1) + lwz 0,IFRAME_R0(1) + lis 30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ + lwz 31,_C_LABEL(intr_depth)@l(30) + addi 31,31,-1 + stw 31,_C_LABEL(intr_depth)@l(30) + b realtrap +1: +/* Here is the normal exit of extintr: */ + lwz 5,IFRAME_CR(1) + lwz 6,IFRAME_LR(1) + mtcr 5 + mtlr 6 + lwz 6,IFRAME_R6(1) + lwz 5,IFRAME_R5(1) + lis 3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ + lwz 4,_C_LABEL(intr_depth)@l(3) + addi 4,4,-1 + stw 4,_C_LABEL(intr_depth)@l(3) + lwz 4,IFRAME_R4(1) + lwz 3,IFRAME_R3(1) + lwz 0,IFRAME_R0(1) + lwz 1,IFRAME_R1(1) + rfi + +/* + * Decrementer interrupt second level handler + */ +decrintr: + INTRENTER + addi 3,1,8 /* intr frame -> clock frame */ + bl _C_LABEL(decr_intr) + b intr_exit + +#if defined(DDB) +/* + * Deliberate entry to ddbtrap + */ + .globl _C_LABEL(ddb_trap) +_C_LABEL(ddb_trap): + mtsprg 1,1 + mfmsr 3 + mtsrr1 3 + andi. 3,3,~(PSL_EE|PSL_ME)@l + mtmsr 3 /* disable interrupts */ + isync + stmw 28,ddbsave(0) + mflr 28 + li 29,EXC_BPT + mtlr 29 + mfcr 29 + mtsrr0 28 +#endif /* DDB */ + +#if defined(DDB) || defined(KGDB) +/* + * Now the ddb trap catching code. + */ +ddbtrap: + FRAME_SETUP(ddbsave) +/* Call C trap code: */ + addi 3,1,8 + bl _C_LABEL(ddb_trap_glue) + or. 3,3,3 + bne ddbleave +/* This wasn't for DDB, so switch to real trap: */ + lwz 3,FRAME_EXC+8(1) /* save exception */ + stw 3,ddbsave+8(0) + FRAME_LEAVE(ddbsave) + mtsprg 1,1 /* prepare for entrance to realtrap */ + stmw 28,tempsave(0) + mflr 28 + mfcr 29 + lwz 31,ddbsave+8(0) + mtlr 31 + b realtrap +ddbleave: + FRAME_LEAVE(ddbsave) + rfi +#endif /* DDB || KGDB */ + +#ifdef IPKDB +/* + * Deliberate entry to ipkdbtrap + */ + .globl _C_LABEL(ipkdb_trap) +_C_LABEL(ipkdb_trap): + mtsprg 1,1 + mfmsr 3 + mtsrr1 3 + andi. 3,3,~(PSL_EE|PSL_ME)@l + mtmsr 3 /* disable interrupts */ + isync + stmw 28,ipkdbsave(0) + mflr 28 + li 29,EXC_BPT + mtlr 29 + mfcr 29 + mtsrr0 28 + +/* + * Now the ipkdb trap catching code. + */ +ipkdbtrap: + FRAME_SETUP(ipkdbsave) +/* Call C trap code: */ + addi 3,1,8 + bl _C_LABEL(ipkdb_trap_glue) + or. 3,3,3 + bne ipkdbleave +/* This wasn't for IPKDB, so switch to real trap: */ + lwz 3,FRAME_EXC+8(1) /* save exception */ + stw 3,ipkdbsave+8(0) + FRAME_LEAVE(ipkdbsave) + mtsprg 1,1 /* prepare for entrance to realtrap */ + stmw 28,tempsave(0) + mflr 28 + mfcr 29 + lwz 31,ipkdbsave+8(0) + mtlr 31 + b realtrap +ipkdbleave: + FRAME_LEAVE(ipkdbsave) + rfi + +ipkdbfault: + ba _ipkdbfault +_ipkdbfault: + mfsrr0 3 + addi 3,3,4 + mtsrr0 3 + li 3,-1 + rfi + +/* + * int ipkdbfbyte(unsigned char *p) + */ + .globl _C_LABEL(ipkdbfbyte) +_C_LABEL(ipkdbfbyte): + li 9,EXC_DSI /* establish new fault routine */ + lwz 5,0(9) + lis 6,ipkdbfault@ha + lwz 6,ipkdbfault@l(6) + stw 6,0(9) +#ifdef IPKDBUSERHACK + lis 8,_C_LABEL(ipkdbsr)@ha + lwz 8,_C_LABEL(ipkdbsr)@l(8) + mtsr USER_SR,8 + isync +#endif + dcbst 0,9 /* flush data... */ + sync + icbi 0,9 /* and instruction caches */ + lbz 3,0(3) /* fetch data */ + stw 5,0(9) /* restore previous fault handler */ + dcbst 0,9 /* and flush data... */ + sync + icbi 0,9 /* and instruction caches */ + blr + +/* + * int ipkdbsbyte(unsigned char *p, int c) + */ + .globl _C_LABEL(ipkdbsbyte) +_C_LABEL(ipkdbsbyte): + li 9,EXC_DSI /* establish new fault routine */ + lwz 5,0(9) + lis 6,ipkdbfault@ha + lwz 6,ipkdbfault@l(6) + stw 6,0(9) +#ifdef IPKDBUSERHACK + lis 8,_C_LABEL(ipkdbsr)@ha + lwz 8,_C_LABEL(ipkdbsr)@l(8) + mtsr USER_SR,8 + isync +#endif + dcbst 0,9 /* flush data... */ + sync + icbi 0,9 /* and instruction caches */ + mr 6,3 + xor 3,3,3 + stb 4,0(6) + dcbst 0,6 /* Now do appropriate flushes + to data... */ + sync + icbi 0,6 /* and instruction caches */ + stw 5,0(9) /* restore previous fault handler */ + dcbst 0,9 /* and flush data... */ + sync + icbi 0,9 /* and instruction caches */ + blr +#endif /* IPKDB */ |