Date: Fri, 6 Apr 2007 00:38:41 GMT From: Andrew Turner<andrew@fubar.geek.nz> To: freebsd-gnats-submit@FreeBSD.org Subject: powerpc/111296: Support IMISS, DLMISS an DSMISS interrupts Message-ID: <200704060038.l360cfju091866@www.freebsd.org> Resent-Message-ID: <200704060050.l360o5e2072751@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 111296 >Category: powerpc >Synopsis: Support IMISS, DLMISS an DSMISS interrupts >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-ppc >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Apr 06 00:50:04 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Andrew Turner >Release: FreeBSD 6.2-STABLE i386 >Organization: >Environment: System: FreeBSD hermies.int.fubar.geek.nz 6.2-STABLE FreeBSD 6.2-STABLE #0: Sat Feb 3 15:23:37 NZDT 2007 root@hermies.int.fubar.geek.nz:/usr/obj/srctrees/RELENG_6/sys/GENERIC i386 >Description: The attached patch adds support for the IMISS, DLMISS an DSMISS interrupts required to run FreeBSD on a G2 core. >How-To-Repeat: >Fix: Patch attached with submission follows: Index: sys/powerpc/powerpc/machdep.c =================================================================== RCS file: /cvsroot/src/sys/powerpc/powerpc/machdep.c,v retrieving revision 1.100 diff -u -r1.100 machdep.c --- sys/powerpc/powerpc/machdep.c 12 Feb 2007 08:59:33 -0000 1.100 +++ sys/powerpc/powerpc/machdep.c 5 Apr 2007 21:26:45 -0000 @@ -253,6 +253,9 @@ extern void *extint, *extsize; extern void *dblow, *dbsize; extern void *vectrap, *vectrapsize; +extern void *imisstrap, *imisssize; +extern void *dlmisstrap, *dlmisssize; +extern void *dsmisstrap, *dsmisssize; void powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) @@ -343,6 +346,9 @@ bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize); + bcopy(&imisstrap, (void *)EXC_IMISS, (size_t)&imisssize); + bcopy(&dlmisstrap, (void *)EXC_DLMISS, (size_t)&dlmisssize); + bcopy(&dsmisstrap, (void *)EXC_DSMISS, (size_t)&dsmisssize); bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize); bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize); bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize); Index: sys/powerpc/powerpc/trap_subr.S =================================================================== RCS file: /cvsroot/src/sys/powerpc/powerpc/trap_subr.S,v retrieving revision 1.16 diff -u -r1.16 trap_subr.S --- sys/powerpc/powerpc/trap_subr.S 23 Dec 2005 13:05:27 -0000 1.16 +++ sys/powerpc/powerpc/trap_subr.S 5 Apr 2007 21:21:15 -0000 @@ -284,6 +284,207 @@ CNAME(alisize) = .-CNAME(alitrap) /* + * It's G2 specific. Instuction TLB miss. + */ + .globl CNAME(imisstrap),CNAME(imisssize) +CNAME(imisstrap): + mfspr %r2, SPR_HASH1 /* get first pointer */ + addi %r1, 0, 8 /* load 8 for counter */ + mfctr %r0 /* save counter */ + mfspr %r3, SPR_ICMP /* get first compare value */ + addi %r2, %r2, -8 /* pre dec the pointer */ +im0: + mtctr %r1 /* load counter */ +im1: + lwzu %r1, 8(%r2) /* get next pte */ + cmp 0, %r1, %r3 /* see if found pte */ + bdnzf 2, im1 /* dec count br if cmp ne and if + * count not zero */ + bne instr_sec_hash /* if not found set up second hash + * or exit */ + lwz %r1, +4(%r2) /* load tlb entry lower-word */ + andi. %r3, %r1, 8 /* check G bit */ + bne do_isi_prot /* if guarded, take an ISI */ + mtctr %r0 /* restore counter */ + mfspr %r0, SPR_IMISS /* get the miss address for the tlbli */ + mfspr %r3, SPR_SRR1 /* get the saved cr0 bits */ + mtcrf 0x80, %r3 /* restore CR0 */ + mtspr SPR_RPA, %r1 /* set the pte */ + ori %r1, %r1, 0x100 /* set reference bit */ + srwi %r1, %r1, 8 /* get byte 7 of pte */ + tlbli %r0 /* load the itlb */ + stb %r1, +6(%r2) /* update page table */ + rfi /* return to executing program */ + +instr_sec_hash: + andi. %r1, %r3, 0x0040 /* see if we have done second hash */ + bne do_isi /* if so, go to ISI interrupt */ + mfspr %r2, SPR_HASH2 /* get the second pointer */ + ori %r3, %r3, 0x0040 /* change the compare value */ + addi %r1, %r0, 8 /* load 8 for counter */ + addi %r2, %r2, -8 /* pre dec for update on load */ + b im0 /* try second hash */ + +/* Create a faked ISI interrupt as the address was not found */ +do_isi_prot: + mfspr %r3, SPR_SRR1 /* get srr1 */ + andi. %r2, %r3, 0xffff /* clean upper srr1 */ + addis %r2, %r2, 0x0800 /* or in srr<4> = 1 to flag prot + * violation */ + b isi1 +do_isi: + mfspr %r3, SPR_SRR1 /* get srr1 */ + andi. %r2, %r3, 0xffff /* clean srr1 */ + addis %r2, %r2, 0x4000 /* or in srr1<1> = 1 to flag pte + * not found */ +isi1: + mtctr %r0 /* restore counter */ + mtspr SPR_SRR1, %r2 /* set srr1 */ + mfmsr %r0 /* get msr */ + xoris %r0, %r0, 0x2 /* flip the msr<tgpr> bit */ + mtcrf 0x80, %r3 /* restore CR0 */ + mtmsr %r0 /* flip back to the native gprs */ + ba EXC_ISI /* go to instr. access interrupt */ + +CNAME(imisssize) = .-CNAME(imisstrap) + +/* + * It's G2 specific. Data load TLB miss. + */ + .globl CNAME(dlmisstrap),CNAME(dlmisssize) +CNAME(dlmisstrap): + mfspr %r2, SPR_HASH1 /* get first pointer */ + addi %r1, 0, 8 /* load 8 for counter */ + mfctr %r0 /* save counter */ + mfspr %r3, SPR_DCMP /* get first compare value */ + addi %r2, %r2, -8 /* pre dec the pointer */ +dm0: + mtctr %r1 /* load counter */ +dm1: + lwzu %r1, 8(%r2) /* get next pte */ + cmp 0, 0, %r1, %r3 /* see if found pte */ + bdnzf 2, dm1 /* dec count br if cmp ne and if + * count not zero */ + bne data_sec_hash /* if not found set up second hash + * or exit */ + lwz %r1, +4(%r2) /* load tlb entry lower-word */ + mtctr %r0 /* restore counter */ + mfspr %r0, SPR_DMISS /* get the miss address for the tlbld */ + mfspr %r3, SPR_SRR1 /* get the saved cr0 bits */ + mtcrf 0x80, %r3 /* restore CR0 */ + mtspr SPR_RPA, %r1 /* set the pte */ + ori %r1, %r1, 0x100 /* set reference bit */ + srwi %r1, %r1, 8 /* get byte 7 of pte */ + tlbld %r0 /* load the dtlb */ + stb %r1, +6(%r2) /* update page table */ + rfi /* return to executing program */ + +data_sec_hash: + andi. %r1, %r3, 0x0040 /* see if we have done second hash */ + bne do_dsi /* if so, go to DSI interrupt */ + mfspr %r2, SPR_HASH2 /* get the second pointer */ + ori %r3, %r3, 0x0040 /* change the compare value */ + addi %r1, 0, 8 /* load 8 for counter */ + addi %r2, %r2, -8 /* pre dec for update on load */ + b dm0 /* try second hash */ + +CNAME(dlmisssize) = .-CNAME(dlmisstrap) + +/* + * It's G2 specific. Data store TLB miss. + */ + .globl CNAME(dsmisstrap),CNAME(dsmisssize) +CNAME(dsmisstrap): + mfspr %r2, SPR_HASH1 /* get first pointer */ + addi %r1, 0, 8 /* load 8 for counter */ + mfctr %r0 /* save counter */ + mfspr %r3, SPR_DCMP /* get first compare value */ + addi %r2, %r2, -8 /* pre dec the pointer */ +ds0: + mtctr %r1 /* load counter */ +ds1: + lwzu %r1, 8(%r2) /* get next pte */ + cmp 0, 0, %r1, %r3 /* see if found pte */ + bdnzf 2, ds1 /* dec count br if cmp ne and if + * count not zero */ + bne data_store_sec_hash /* if not found set up second hash + * or exit */ + lwz %r1, +4(%r2) /* load tlb entry lower-word */ + andi. %r3, %r1, 0x80 /* check the C-bit */ + beq data_store_chk_prot /* if (C==0) + * go check protection modes */ +ds2: + mtctr %r0 /* restore counter */ + mfspr %r0, SPR_DMISS /* get the miss address for the tlbld */ + mfspr %r3, SPR_SRR1 /* get the saved cr0 bits */ + mtcrf 0x80, %r3 /* restore CR0 */ + mtspr SPR_RPA, %r1 /* set the pte */ + tlbld %r0 /* load the dtlb */ + rfi /* return to executing program */ + +data_store_sec_hash: + andi. %r1, %r3, 0x0040 /* see if we have done second hash */ + bne do_dsi /* if so, go to DSI interrupt */ + mfspr %r2, SPR_HASH2 /* get the second pointer */ + ori %r3, %r3, 0x0040 /* change the compare value */ + addi %r1, 0, 8 /* load 8 for counter */ + addi %r2, %r2, -8 /* pre dec for update on load */ + b ds0 /* try second hash */ + +/* Check the protection before setting PTE(c-bit) */ +data_store_chk_prot: + rlwinm. %r3,%r1,30,0,1 /* test PP */ + bge- chk0 /* if (PP == 00 or PP == 01) + * goto chk0: */ + andi. %r3, %r1, 1 /* test PP[0] */ + beq+ chk2 /* return if PP[0] == 0 */ + b do_dsi_prot /* else DSIp */ +chk0: + mfspr %r3,SPR_SRR1 /* get old msr */ + andis. %r3,%r3,0x0008 /* test the KEY bit (SRR1-bit 12) */ + beq chk2 /* if (KEY==0) goto chk2: */ + b do_dsi_prot /* else do_dsi_prot */ +chk2: + ori %r1, %r1, 0x180 /* set reference and change bit */ + sth %r1, 6(%r2) /* update page table */ + b ds2 /* and back we go */ + +/* Create a faked DSI interrupt as the address was not found */ +do_dsi: + mfspr %r3, SPR_SRR1 /* get srr1 */ + rlwinm %r1,%r3,9,6,6 /* get srr1<flag> to bit 6 for + * load/store, zero rest */ + addis %r1, %r1, 0x4000 /* or in dsisr<1> = 1 to flag pte + * not found */ + b dsi1 + +do_dsi_prot: + mfspr %r3, SPR_SRR1 /* get srr1 */ + rlwinm %r1,%r3,9,6,6 /* get srr1<flag> to bit 6 for + *load/store, zero rest */ + addis %r1, %r1, 0x0800 /* or in dsisr<4> = 1 to flag prot + * violation */ + +dsi1: + mtctr %r0 /* restore counter */ + andi. %r2, %r3, 0xffff /* clear upper bits of srr1 */ + mtspr SPR_SRR1, %r2 /* set srr1 */ + mtspr SPR_DSISR, %r1 /* load the dsisr */ + mfspr %r1, SPR_DMISS /* get miss address */ + rlwinm. %r2,%r2,0,31,31 /* test LE bit */ + beq dsi2 /* if little endian then: */ + xor %r1, %r1, 0x07 /* de-mung the data address */ +dsi2: + mtspr SPR_DAR, %r1 /* put in dar */ + mfmsr %r0 /* get msr */ + xoris %r0, %r0, 0x2 /* flip the msr<tgpr> bit */ + mtcrf 0x80, %r3 /* restore CR0 */ + mtmsr %r0 /* flip back to the native gprs */ + ba EXC_DSI /* branch to DSI interrupt */ + +CNAME(dsmisssize) = .-CNAME(dsmisstrap) + +/* * Similar to the above for DSI * Has to handle BAT spills * and standard pagetable spills >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704060038.l360cfju091866>