Skip site navigation (1)Skip section navigation (2)
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>