Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Feb 2007 10:04:33 +1300
From:      Andrew Turner <andrew@fubar.geek.nz>
To:        freebsd-ppc@freebsd.org
Subject:   Patch to partially boot an EFIKA
Message-ID:  <20070219100433.66d7ff49@hermies.int.fubar.geek.nz>

index | next in thread | raw e-mail

[-- Attachment #1 --]
The attached patch helps me to partially boot my EFIKA. The file
ofwread.S is from NetBSD and needs to be placed in sys/powerpc/powerpc.

The patch takes the real-mode ofw interface code from NetBSD and the
TLB exception handlers from //depot/user/jaras in perforce.

The call to ofwr_init in locore.S is not enabled by default as
it doesn't currently work on my Apple. By commenting out the
FIRMWORKSBUGS ifdef, to call ofwr_init, I can get my EFIKA to boot until
it attempts to schedule work.

Andrew
[-- Attachment #2 --]
/*	$NetBSD: ofwreal.S,v 1.9 2007/01/14 22:11:27 aymeric Exp $	*/

/*
 * Copyright (C) 1996 Wolfgang Solfrank.
 * Copyright (C) 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.
 */

/*
 * This file provides a real-mode client interface on machines, that
 * (incorrectly) only implement virtual mode client interface.
 *
 * It assumes though, that any actual memory in the machine is
 * mapped 1:1 even by the virtual mode OpenFirmware.
 * Furthermore it assumes that addresses returned by OpenFirmware are not
 * accessed by the client.
 *
 * TODO: handle set-callback specially
 */
#include <machine/psl.h>
#include <machine/trap.h>
#define _NOREGNAMES
#include <machine/asm.h>

#define	CACHELINE	32		/* Note that this value is really
					   hardwired */

	.data
ofentry:
	.long	0			/* actual entry to firmware in
					   virtual mode */

#define	BATSIZE		(8*8)
#define	SRSIZE		(16*4)
#define	SPRGSIZE	(4*4)
#define	SDR1SIZE	4
#define	SI1SIZE		(2*256)
#define	SI2SIZE		(3*256)
#define	SVSIZE		(BATSIZE+SRSIZE+SPRGSIZE+SDR1SIZE+SI1SIZE+SI2SIZE)

	.local	fwsave
	.comm	fwsave,SVSIZE,8

	.local	clsave
	.comm	clsave,SVSIZE,8

ENTRY(ofwr_init)
	mflr	%r31			/* save return address */

	mr	%r13,%r6		/* save args */
	mr	%r12,%r7		/* save argslen */
	lis	%r8,ofentry@ha
	stw	%r5,ofentry@l(%r8)	/* save virtual mode firmware entry */

	lis	%r3,fwsave@ha		/* save the mmu values of the
					   firmware */
	addi	%r3,%r3,fwsave@l
	bl	savemmu

	lis	%r5,fwentry@ha		/* get new firmware entry */
	addi	%r5,%r5,fwentry@l

	mr	%r6,%r13		/* restore args pointer */
	mr	%r7,%r12		/* restore args length */
	mtlr	%r31			/* restore return address */
	blr

/*
 * Emulated firmware entry.
 */
fwentry:
	mflr	%r0			/* save return address */
	stw	%r0,4(%r1)
	stwu	%r1,-16(%r1)		/* setup stack frame */
	stw	%r3,8(%r1)		/* save arg */

	lis	%r3,clsave@ha		/* save mmu values of client */
	addi	%r3,%r3,clsave@l
	bl	savemmu

	lis	%r3,fwsave@ha		/* restore mmu values of firmware */
	addi	%r3,%r3,fwsave@l
	bl	restoremmu

	lis	%r3,ofentry@ha
	lwz	%r3,ofentry@l(%r3)	/* get actual firmware entry */
	mtlr	%r3

	mfmsr	%r4
	stw	%r4,12(%r1)		/* save MSR */
	ori	%r4,%r4,PSL_IR|PSL_DR	/* turn on MMU */
	andi.	%r4,%r4,~PSL_EE@l	/* turn off interrupts */
	mtmsr	%r4
	isync

	lwz	%r3,8(%r1)		/* restore arg */
	blrl				/* do actual firmware call */
	stw	%r3,8(%r1)		/* save return value */

	lwz	%r4,12(%r1)		/* get saved MSR */
	mtmsr	%r4
	isync

	lis	%r3,fwsave@ha		/* save mmu values of firmare */
	addi	%r3,%r3,fwsave@l	/* (might not be necessary, but... */
	bl	savemmu

	lis	%r3,clsave@ha		/* restore mmu values of client */
	addi	%r3,%r3,clsave@l
	bl	restoremmu

	lwz	%r3,8(%r1)		/* restore return value */
	lwz	%r1,0(%r1)		/* and return */
	lwz	%r0,4(%r1)
	mtlr	%r0
	blr

/*
 * Save everyting related to the mmu to the saveare pointed to by r3.
 */
savemmu:

	mfibatl	%r4,0			/* save BATs */
	stw	%r4,0(%r3)
	mfibatu	%r4,0
	stw	%r4,4(%r3)
	mfibatl	%r4,1
	stw	%r4,8(%r3)
	mfibatu	%r4,1
	stw	%r4,12(%r3)
	mfibatl	%r4,2
	stw	%r4,16(%r3)
	mfibatu	%r4,2
	stw	%r4,20(%r3)
	mfibatl	%r4,3
	stw	%r4,24(%r3)
	mfibatu	%r4,3
	stw	%r4,28(%r3)
	mfdbatl	%r4,0
	stw	%r4,32(%r3)
	mfdbatu	%r4,0
	stw	%r4,36(%r3)
	mfdbatl	%r4,1
	stw	%r4,40(%r3)
	mfdbatu	%r4,1
	stw	%r4,44(%r3)
	mfdbatl	%r4,2
	stw	%r4,48(%r3)
	mfdbatu	%r4,2
	stw	%r4,52(%r3)
	mfdbatl	%r4,3
	stw	%r4,56(%r3)
	mfdbatu	%r4,3
	stwu	%r4,60(%r3)

	li	%r4,0			/* save SRs */
1:
	addis	%r4,%r4,-0x10000000@ha
	or.	%r4,%r4,%r4
	mfsrin	%r5,%r4
	stwu	%r5,4(%r3)
	bne	1b

	mfsprg0	%r4			/* save SPRGs */
	stw	%r4,4(%r3)
	mfsprg1	%r4
	stw	%r4,8(%r3)
	mfsprg2	%r4
	stw	%r4,12(%r3)
	mfsprg3	%r4
	stw	%r4,16(%r3)

	mfsdr1	%r4			/* save SDR1 */
	stw	%r4,20(%r3)

	addi	%r4,%r3,24
	mflr	%r11
	li	%r3,EXC_DSI		/* save DSI/ISI trap vectors */
	li	%r5,SI1SIZE
	bl	copy

	mtlr	%r11
	li	%r3,EXC_IMISS		/* save MISS trap vectors */
	li	%r5,SI2SIZE

/* Copy an exception handler */
copy:
	li	%r6,CACHELINE
1:
	lwz	%r7,0(%r3)
	lwz	%r8,4(%r3)
	lwz	%r9,8(%r3)
	lwz	%r10,12(%r3)
	stw	%r7,0(%r4)
	stw	%r8,4(%r4)
	stw	%r9,8(%r4)
	stw	%r10,12(%r4)
	lwz	%r7,16(%r3)
	lwz	%r8,20(%r3)
	lwz	%r9,24(%r3)
	lwz	%r10,28(%r3)
	stw	%r7,16(%r4)
	stw	%r8,20(%r4)
	stw	%r9,24(%r4)
	stw	%r10,28(%r4)
	dcbst	%r0,%r4
	icbi	%r0,%r4
	add	%r3,%r3,%r6
	add	%r4,%r4,%r6
	subf.	%r5,%r6,%r5
	bgt	1b

	dcbst	%r0,%r4
	icbi	%r0,%r4

	sync
	isync

	blr

/*
 * Restore everyting related to the mmu from the saveare pointed to by r3.
 */
restoremmu:
	mfmsr	%r12
	andi.	%r4,%r12,~(PSL_IR|PSL_DR)@l
	mtmsr	%r4			/* Disable MMU */
	isync

	li	%r4,0			/* first, invalidate BATs */
	mtibatu	0,%r4
	mtibatu	1,%r4
	mtibatu	2,%r4
	mtibatu	3,%r4
	mtdbatu	0,%r4
	mtdbatu	1,%r4
	mtdbatu	2,%r4
	mtdbatu	3,%r4

	lwz	%r4,0(%r3)
	mtibatl	0,%r4			/* restore BATs */
	lwz	%r4,4(%r3)
	mtibatu	0,%r4
	lwz	%r4,8(%r3)
	mtibatl	1,%r4
	lwz	%r4,12(%r3)
	mtibatu	1,%r4
	lwz	%r4,16(%r3)
	mtibatl	2,%r4
	lwz	%r4,20(%r3)
	mtibatu	2,%r4
	lwz	%r4,24(%r3)
	mtibatl	3,%r4
	lwz	%r4,28(%r3)
	mtibatu	3,%r4
	lwz	%r4,32(%r3)
	mtdbatl	0,%r4
	lwz	%r4,36(%r3)
	mtdbatu	0,%r4
	lwz	%r4,40(%r3)
	mtdbatl	1,%r4
	lwz	%r4,44(%r3)
	mtdbatu	1,%r4
	lwz	%r4,48(%r3)
	mtdbatl	2,%r4
	lwz	%r4,52(%r3)
	mtdbatu	2,%r4
	lwz	%r4,56(%r3)
	mtdbatl	3,%r4
	lwzu	%r4,60(%r3)
	mtdbatu	3,%r4

	li	%r4,0			/* restore SRs */
1:
	lwzu	%r5,4(%r3)
	addis	%r4,%r4,-0x10000000@ha
	or.	%r4,%r4,%r4
	mtsrin	%r5,%r4
	bne	1b

	lwz	%r4,4(%r3)
	mtsprg0	%r4			/* restore SPRGs */
	lwz	%r4,8(%r3)
	mtsprg1	%r4
	lwz	%r4,12(%r3)
	mtsprg2	%r4
	lwz	%r4,16(%r3)
	mtsprg3	%r4

	sync				/* remove everything from tlb */
	lis	%r4,0x40000@ha
	li	%r5,0x1000
1:
	subf.	%r4,%r5,%r4
	tlbie	%r4
	bne	1b

	sync
	tlbsync
	sync

	lwz	%r4,20(%r3)
	sync
	mtsdr1	%r4			/* restore SDR1 */

	addi	%r3,%r3,24
	mflr	%r11
	li	%r4,EXC_DSI		/* restore DSI/ISI trap vectors */
	li	%r5,SI1SIZE
	bl	copy

	li	%r4,EXC_IMISS		/* restore MISS trap vectors */
	li	%r5,SI2SIZE
	bl	copy

	/* tlbia */
	sync
	li	%r3,0x40
	mtctr	%r3
	li	%r4,0
    1:
	tlbie	%r4
	addi	%r4,%r4,0x1000
	bdnz	1b
	sync
	tlbsync
	sync

	mtmsr	%r12			/* restore MMU */
	mtlr	%r11
	blr

[-- Attachment #3 --]
Index: sys/conf/files.powerpc
===================================================================
RCS file: /cvsroot/src/sys/conf/files.powerpc,v
retrieving revision 1.60
diff -u -r1.60 files.powerpc
--- sys/conf/files.powerpc	23 Oct 2006 13:05:01 -0000	1.60
+++ sys/conf/files.powerpc	8 Jan 2007 09:21:55 -0000
@@ -56,6 +56,7 @@
 powerpc/powerpc/nexus.c		standard
 powerpc/powerpc/ofwmagic.S	standard
 powerpc/powerpc/ofw_machdep.c	standard
+powerpc/powerpc/ofwreal.S	standard
 powerpc/powerpc/openpic.c	standard
 powerpc/powerpc/pic_if.m	standard
 powerpc/powerpc/pmap_dispatch.c	standard
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	18 Feb 2007 20:47:41 -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	18 Feb 2007 20:40:25 -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.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	18 Feb 2007 20:40: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)
@@ -347,6 +350,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(&imisstrap, (void *)EXC_IMISS,  (size_t)&imisssize);
+	bcopy(&dlmisstrap, (void *)EXC_DLMISS,  (size_t)&dlmisssize);
+	bcopy(&dsmisstrap, (void *)EXC_DSMISS,  (size_t)&dsmisssize);
 #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	18 Feb 2007 20:54:16 -0000
@@ -284,6 +284,292 @@
 CNAME(alisize) = .-CNAME(alitrap)
 
 /*
+ * It's G2 specific. Instuction TLB miss.
+ */
+	.globl	CNAME(imisstrap),CNAME(imisssize)
+CNAME(imisstrap):
+/*
+ *    Instruction TLB miss flow
+ *    Entry:
+ *    Vec = 1000
+ *    srr0 -> address of instruction that missed
+ *    srr1 -> 0:3=cr0 4=lru way bit 16:31 = saved MSR
+ *    msr<tgpr> -> 1
+ *    iMiss -> ea that missed
+ *    iCmp -> the compare value for the va that missed
+ *    hash1 -> pointer to first hash pteg
+ *    hash2 -> pointer to second hash pteg
+ *    
+ *    Register usage:
+ *    r0 is saved counter
+ *    r1 is junk
+ *    r2 is pointer to pteg
+ *    r3 is current compare value
+ */
+
+	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 instrSecHash		/* 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 doISIp			/* 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 */
+/*
+ * register usage:
+ *  r0 is saved counter
+ *  r1 is junk
+ *  r2 is pointer to pteg
+ *  r3 is current compare value
+ */
+instrSecHash:
+	andi. %r1, %r3, 0x0040		/* see if we have done second hash */
+	bne doISI			/* 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 */
+/*
+ * entry Not Found: synthesize an ISI interrupt
+ * guarded memory protection violation: synthesize an ISI interrupt
+ * Entry:
+ * r0 is saved counter
+ * r1 is junk
+ * r2 is pointer to pteg
+ * r3 is current compare value
+ */
+ 
+doISIp:
+	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
+doISI:
+	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 0x400			/* go to instr. access interrupt */
+
+CNAME(imisssize) = .-CNAME(imisstrap)
+
+/*
+ * It's G2 specific. Data load TLB miss.
+ */
+	.globl	CNAME(dlmisstrap),CNAME(dlmisssize)
+CNAME(dlmisstrap):
+/*
+ * Data TLB miss flow
+ * Entry:
+ * Vec = 1100
+ * srr0 -> address of instruction that caused data tlb miss
+ * srr1 -> 0:3=cr0 4=lru way bit 5=1 if store 16:31 = saved MSR
+ * msr<tgpr> -> 1
+ * dMiss -> ea that missed
+ * dCmp -> the compare value for the va that missed
+ * hash1 -> pointer to first hash pteg
+ * hash2 -> pointer to second hash pteg
+ *
+ * Register usage:
+ * r0 is saved counter
+ * r1 is junk
+ * r2 is pointer to pteg
+ * r3 is current compare value
+ */
+
+	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 dataSecHash			/* 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 */
+/*
+ * Register usage:
+ * r0 is saved counter
+ * r1 is junk
+ * r2 is pointer to pteg
+ * r3 is current compare value
+ */
+ 
+dataSecHash:
+	andi. %r1, %r3, 0x0040		/* see if we have done second hash */
+	bne doDSI			/* 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):
+
+/*
+ * Data TLB miss flow
+ * C=0 in dtlb and dtlb miss on store flow
+ * Entry:
+ * Vec = 1200
+ * srr0 -> address of store that caused the interrupt
+ * srr1 -> 0:3=cr0 4=lru way bit 5=1 16:31 = saved MSR
+ * msr<tgpr> -> 1
+ * dMiss -> ea that missed
+ * dCmp -> the compare value for the va that missed
+ * hash1 -> pointer to first hash pteg
+ * hash2 -> pointer to second hash pteg
+ *
+ * Register usage:
+ * r0 is saved counter
+ * r1 is junk
+ * r2 is pointer to pteg
+ * r3 is current compare value
+ */
+	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 */
+ceq0:
+	mtctr %r1			/* load counter */
+ceq1:
+	lwzu %r1, 8(%r2)		/* get next pte */
+	cmp 0, 0, %r1, %r3		/* see if found pte */
+	bdnzf 2, ceq1			/* dec count br if cmp ne and if count not zero */
+	bne cEq0SecHash			/* 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 cEq0ChkProt			/* if (C==0) go check protection modes */
+ceq2:
+	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 */
+/*
+ * Register usage:
+ * r0 is saved counter
+ * r1 is junk
+ * r2 is pointer to pteg
+ * r3 is current compare value
+*/
+
+cEq0SecHash:
+	andi. %r1, %r3, 0x0040		/* see if we have done second hash */
+	bne doDSI			/* 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 ceq0				/* try second hash */
+	
+/*
+ * entry found and PTE(c-bit==0):
+ * (check protection before setting PTE(c-bit)
+ * Register usage:
+ * r0 is saved counter
+ * r1 is PTE entry
+ * r2 is pointer to pteg
+ * r3 is trashed
+ */
+cEq0ChkProt:
+	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 doDSIp			/* 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 doDSIp			/* else DSIp */
+chk2:
+	ori %r1, %r1, 0x180		/* set reference and change bit */
+	sth %r1, 6(%r2)			/* update page table */
+	b ceq2				/* and back we go */
+	
+/*
+ * entry Not Found: synthesize a DSI interrupt
+ * Entry:
+ * r0 is saved counter
+ * r1 is junk
+ * r2 is pointer to pteg
+ * r3 is current compare value
+ */
+doDSI:
+	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
+doDSIp:
+	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 0x300			/* branch to DSI interrupt */
+
+CNAME(dsmisssize) = .-CNAME(dsmisstrap)
+
+/*
  * Similar to the above for DSI
  * Has to handle BAT spills
  * and standard pagetable spills
home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070219100433.66d7ff49>