Date: Wed, 20 Dec 2006 19:26:14 +1300 From: Andrew Turner <andrew@fubar.geek.nz> To: Peter Grehan <grehan@freebsd.org> Cc: grehan@freebsd.org, freebsd-ppc@freebsd.org Subject: Re: FreeBSD on an Efika Message-ID: <20061220192614.04c53dbf@hermies.int.fubar.geek.nz> In-Reply-To: <4587316C.1070500@freebsd.org> References: <20061218104841.72ba51ea@hermies.int.fubar.geek.nz> <4585CCC1.7050005@freebsd.org> <20061218222327.308dca53@hermies.int.fubar.geek.nz> <4586CA29.10803@freebsd.org> <20061219113230.34182787@hermies.int.fubar.geek.nz> <4587316C.1070500@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--MP_UpkjTp9EV.oiE3bclM4Ix92 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline On Mon, 18 Dec 2006 16:25:16 -0800 Peter Grehan <grehan@freebsd.org> wrote: > a) Put in exception handlers at 0x1000, 0x1100 and 0x1200 to catch > the TLB miss e.g. > > bcopy(&trapcode, (void *)0x1000, (size_t)&trapsize); > > As you can see in <machine/trap.h>, the existing vector definition > don't match these, or are incorrect for the G2 core. There is EXC_IMISS, EXC_DLMISS and EXC_DSMISS. > d) Now the fun part: for those exceptions, change the handler to > point to code that will walk the PTEG table and insert a TLB if > found. If not found, fake a DSI or ISI trap. This can be done in C, > though you will have to be careful to use a pre-allocated stack and > not touch any virtual addresses while doing this, since it could > result in another fault. The attached patch adds the NetBSD handlers. There is a bug in the patch where I can read data once but on the next read or write the kernel crashes. Andrew --MP_UpkjTp9EV.oiE3bclM4Ix92 Content-Type: text/x-patch; name=efika-1.diff Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=efika-1.diff Index: sys/powerpc/include/psl.h =================================================================== RCS file: /cvsroot/src/sys/powerpc/include/psl.h,v retrieving revision 1.4 diff -u -r1.4 psl.h --- sys/powerpc/include/psl.h 7 Jan 2005 02:29:19 -0000 1.4 +++ sys/powerpc/include/psl.h 19 Dec 2006 11:44:10 -0000 @@ -46,6 +46,7 @@ */ #define PSL_VEC 0x02000000 /* AltiVec vector unit available */ #define PSL_POW 0x00040000 /* power management */ +#define PSL_TGPR 0x00020000 /* temp. gpr remapping (mpc603e) */ #define PSL_ILE 0x00010000 /* interrupt endian mode (1 == le) */ #define PSL_EE 0x00008000 /* external interrupt enable */ #define PSL_PR 0x00004000 /* privilege mode (1 == user) */ Index: sys/powerpc/powerpc/locore.S =================================================================== RCS file: /cvsroot/src/sys/powerpc/powerpc/locore.S,v retrieving revision 1.22 diff -u -r1.22 locore.S --- sys/powerpc/powerpc/locore.S 30 Oct 2005 21:29:59 -0000 1.22 +++ sys/powerpc/powerpc/locore.S 19 Dec 2006 11:44:18 -0000 @@ -66,6 +66,7 @@ #include <machine/spr.h> #include <machine/psl.h> #include <machine/asm.h> +#include <machine/pte.h> /* Locate the per-CPU data structure */ #define GET_CPUINFO(r) \ Index: sys/powerpc/powerpc/machdep.c =================================================================== RCS file: /cvsroot/src/sys/powerpc/powerpc/machdep.c,v retrieving revision 1.98 diff -u -r1.98 machdep.c --- sys/powerpc/powerpc/machdep.c 6 Dec 2006 06:34:56 -0000 1.98 +++ sys/powerpc/powerpc/machdep.c 20 Dec 2006 00:27:47 -0000 @@ -256,6 +256,9 @@ extern void *extint, *extsize; extern void *dblow, *dbsize; extern void *vectrap, *vectrapsize; +extern void *tlbimiss, *tlbimsize; +extern void *tlbdlmiss, *tlbdlmsize; +extern void *tlbdsmiss, *tlbdsmsize; void powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) @@ -350,6 +353,9 @@ bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize); bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize); bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize); + bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize); + bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize); + bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize); #ifdef KDB bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize); bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize); 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 20 Dec 2006 00:30:53 -0000 @@ -342,6 +342,205 @@ CNAME(dsisize) = .-CNAME(dsitrap) /* + * Now the tlb software load for 603 processors: + * (Code essentially from the 603e User Manual, Chapter 5, but + * corrected a lot.) + */ + +/* + * For tlb instruction misses + */ + .globl CNAME(tlbimiss),CNAME(tlbimsize) +CNAME(tlbimiss): + mfspr %r2,SPR_HASH1 /* get first pointer */ + li %r1,8 + mfctr %r0 /* save counter */ + mfspr %r3,SPR_ICMP /* get first compare value */ + addi %r2,%r2,-8 /* predec pointer */ +1: + mtctr %r1 /* load counter */ +2: + lwzu %r1,8(%r2) /* get next pte */ + cmpl %cr0,%r1,%r3 /* see if found pte */ + bdnzf 2,2b /* loop if not eq */ + bne 3f /* not found */ + lwz %r1,4(%r2) /* load tlb entry lower word */ + andi. %r3,%r1,PTE_G /* check G-bit */ + bne 4f /* if guarded, take ISI */ + mtctr %r0 /* restore counter */ + mfspr %r0,SPR_IMISS /* get the miss address for the tlbli */ + mfsrr1 %r3 /* get the saved cr0 bits */ + mtcrf 0x80,%r3 /* and restore */ + ori %r1,%r1,PTE_REF /* set the reference bit */ + mtspr SPR_RPA,1 /* set the pte */ + srwi %r1,%r1,8 /* get byte 7 of pte */ + tlbli %r0 /* load the itlb */ + stb %r1,6(%r2) /* update page table */ + RFI + +3: /* not found in pteg */ + andi. %r1,%r3,PTE_HID /* have we already done second hash? */ + bne 5f + mfspr %r2,SPR_HASH2 /* get the second pointer */ + ori %r3,%r3,PTE_HID /* change the compare value */ + li %r1,8 + addi %r2,%r2,-8 /* predec pointer */ + b 1b +4: /* guarded */ + mfsrr1 %r3 + andi. %r2,%r3,0xffff /* clean upper srr1 */ + oris %r2,%r2,DSISR_PROTECT@h /* set srr<4> to flag prot violation */ + b 6f +5: /* not found anywhere */ + mfsrr1 %r3 + andi. %r2,%r3,0xffff /* clean upper srr1 */ + oris %r2,%r2,DSISR_NOTFOUND@h /* set srr1<1> to flag pte not found */ +6: + mtctr %r0 /* restore counter */ + mtsrr1 %r2 + mfmsr %r0 + xoris %r0,%r0,PSL_TGPR@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,%r3 /* restore cr0 */ + mtmsr %r0 /* now with native gprs */ + isync + ba EXC_ISI +CNAME(tlbimsize) = .-CNAME(tlbimiss) + +/* + * For tlb data load misses + */ + .globl CNAME(tlbdlmiss),CNAME(tlbdlmsize) +CNAME(tlbdlmiss): + mfspr %r2,SPR_HASH1 /* get first pointer */ + li %r1,8 + mfctr %r0 /* save counter */ + mfspr %r3,SPR_DCMP /* get first compare value */ + addi %r2,%r2,-8 /* predec pointer */ +1: + mtctr %r1 /* load counter */ +2: + lwzu %r1,8(%r2) /* get next pte */ + cmpl %cr0,%r1,%r3 /* see if found pte */ + bdnzf 2,2b /* loop if not eq */ + bne 3f /* not found */ + lwz %r1,4(%r2) /* load tlb entry lower word */ + mtctr %r0 /* restore counter */ + mfspr %r0,SPR_DMISS /* get the miss address for the tlbld */ + mfsrr1 %r3 /* get the saved cr0 bits */ + mtcrf 0x80,%r3 /* and restore */ + ori %r1,%r1,PTE_REF /* set the reference bit */ + mtspr SPR_RPA,%r1 /* set the pte */ + srwi %r1,%r1,8 /* get byte 7 of pte */ + tlbld %r0 /* load the dtlb */ + stb %r1,6(%r2) /* update page table */ + RFI + +3: /* not found in pteg */ + andi. %r1,%r3,PTE_HID /* have we already done second hash? */ + bne 5f + mfspr %r2,SPR_HASH2 /* get the second pointer */ + ori %r3,%r3,PTE_HID /* change the compare value */ + li %r1,8 + addi %r2,%r2,-8 /* predec pointer */ + b 1b +5: /* not found anywhere */ + mfsrr1 %r3 + lis %r1,DSISR_NOTFOUND@h /* set dsisr<1> to flag pte not found */ + mtctr %r0 /* restore counter */ + andi. %r2,%r3,0xffff /* clean upper srr1 */ + mtsrr1 %r2 + mtdsisr %r1 /* load the dsisr */ + mfspr %r1,SPR_DMISS /* get the miss address */ + mtdar %r1 /* put in dar */ + mfmsr %r0 + xoris %r0,%r0,PSL_TGPR@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,%r3 /* restore cr0 */ + mtmsr %r0 /* now with native gprs */ + isync + ba EXC_DSI +CNAME(tlbdlmsize) = .-CNAME(tlbdlmiss) + +/* + * For tlb data store misses + */ + .globl CNAME(tlbdsmiss),CNAME(tlbdsmsize) +CNAME(tlbdsmiss): + mfspr %r2,SPR_HASH1 /* get first pointer */ + li %r1,%r8 + mfctr %r0 /* save counter */ + mfspr %r3,SPR_DCMP /* get first compare value */ + addi %r2,%r2,-8 /* predec pointer */ +1: + mtctr %r1 /* load counter */ +2: + lwzu %r1,8(%r2) /* get next pte */ + cmpl %cr0,%r1,%r3 /* see if found pte */ + bdnzf 2,2b /* loop if not eq */ + bne 3f /* not found */ + lwz %r1,4(%r2) /* load tlb entry lower word */ + andi. %r3,%r1,PTE_CHG /* check the C-bit */ + beq 4f +5: + mtctr %r0 /* restore counter */ + mfspr %r0,SPR_DMISS /* get the miss address for the tlbld */ + mfsrr1 %r3 /* get the saved cr0 bits */ + mtcrf 0x80,%r3 /* and restore */ + mtspr SPR_RPA,%r1 /* set the pte */ + tlbld %r0 /* load the dtlb */ + RFI + +3: /* not found in pteg */ + andi. %r1,%r3,PTE_HID /* have we already done second hash? */ + bne 5f + mfspr %r2,SPR_HASH2 /* get the second pointer */ + ori %r3,%r3,PTE_HID /* change the compare value */ + li %r1,8 + addi %r2,%r2,-8 /* predec pointer */ + b 1b +4: /* found, but C-bit = 0 */ + rlwinm. %r3,%r1,30,0,1 /* test PP */ + bge- 7f + andi. %r3,%r1,1 + beq+ 8f +9: /* found, but protection violation (PP==00)*/ + mfsrr1 %r3 + lis %r1,(DSISR_PROTECT|DSISR_STORE)@h + /* indicate protection violation + on store */ + b 1f +7: /* found, PP=1x */ + mfspr %r3,SPR_DMISS /* get the miss address */ + mfsrin %r1,%r3 /* get the segment register */ + mfsrr1 %r3 + rlwinm %r3,%r3,18,31,31 /* get PR-bit */ + rlwnm. %r2,%r2,%r3,1,1 /* get the key */ + bne- 9b /* protection violation */ +8: /* found, set reference/change bits */ + lwz %r1,4(%r2) /* reload tlb entry */ + ori %r1,%r1,(PTE_REF|PTE_CHG) + sth %r1,6(%r2) + b 5b +5: /* not found anywhere */ + mfsrr1 %r3 + lis %r1,(DSISR_NOTFOUND|DSISR_STORE)@h + /* set dsisr<1> to flag pte not found */ + /* dsisr<6> to flag store */ +1: + mtctr %r0 /* restore counter */ + andi. %r2,%r3,0xffff /* clean upper srr1 */ + mtsrr1 %r2 + mtdsisr %r1 /* load the dsisr */ + mfspr %r1,SPR_DMISS /* get the miss address */ + mtdar %r1 /* put in dar */ + mfmsr %r0 + xoris %r0,%r0,PSL_TGPR@h /* flip the msr<tgpr> bit */ + mtcrf 0x80,%r3 /* restore cr0 */ + mtmsr %r0 /* now with native gprs */ + isync + ba EXC_DSI +CNAME(tlbdsmsize) = .-CNAME(tlbdsmiss) + +/* * Preamble code for DSI/ISI traps */ disitrap: --MP_UpkjTp9EV.oiE3bclM4Ix92--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20061220192614.04c53dbf>