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