Subject: Re: port-mips/31915: provide centralized wired_map logic
To: None <tsutsui@netbsd.org, gnats-admin@netbsd.org,>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: netbsd-bugs
Date: 11/03/2005 16:13:01
The following reply was made to PR port-mips/31915; it has been noted by GNATS.

From: "Garrett D'Amore" <garrett_damore@tadpole.com>
To: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
Cc: soda@sra.co.jp, gnats-bugs@NetBSD.org, port-mips@NetBSD.org
Subject: Re: port-mips/31915: provide centralized wired_map logic
Date: Thu, 03 Nov 2005 08:09:52 -0800

 Izumi Tsutsui wrote:
 
 >I've integrated your patch into my local ews4800mips tree,
 >and now it works with some tweaks. I'll try to adapt arc port next,
 >but I'd like to post the tweaks for a note.
 >
 >In article <4368EF9E.1040104@tadpole.com>
 >garrett_damore@tadpole.com wrote:
 >
 >  
 >
 >>OK.  (Aside: what if someone ever wants to do a MIPS-I wired map?  I 
 >>guess they have to #ifdef around it.  We can cross that bridge if we 
 >>ever get to it, I suppose.)
 >>    
 >>
 >
 >Well, I don't know about MIPS-I TLB very well, but for now
 >all arc machines have MIPS3 CPUs and no other ports use
 >wired map so there is no problem.
 >
 >  
 >
 >>OK, its just naming.  I'm not picky.  But if we do that, we should 
 >>probably also rename mips3_wire_down to mips3_wired_enter_region.
 >>    
 >>
 >
 >Hmm, I thought that pmap_enter(9) takes size args, but it was wrong
 >(though pmap_remove(9) takes eva for region). Ok, I'll leave them
 >mips3_wired_enter_page() and mips3_wire_enter_region() as you suggested.
 >
 >  
 >
 >>Yes, I suppose it could.  I think I'll just use KASSERT instead, though.
 >>    
 >>
 >
 >Yeah, it's fine.
 >
 >  
 >
 >>Index: mips/include/wired_map.h
 >>    
 >>
 > :
 >  
 >
 >>+struct wired_map_entry {
 >>+	paddr_t	pa0;
 >>+	paddr_t	pa1;
 >>+	vaddr_t	va;
 >>+	vsize_t	pgmask;
 >>+} wired_map[MIPS3_NWIRED_ENTRY];
 >>    
 >>
 >
 >This declaration for wired_map variable is not needed here?
 >(only struct declaration is needed)
 >  
 >
 Oops I missed that one!
 
 >  
 >
 >>Index: mips/mips/wired_map.c
 >>    
 >>
 > :
 >  
 >
 >>+struct wired_map_entry {
 >>+	paddr_t	pa0;
 >>+	paddr_t	pa1;
 >>+	vaddr_t	va;
 >>+	vsize_t	pgmask;
 >>+} mips3_wired_map[MIPS3_NWIRED_ENTRY];
 >>    
 >>
 >
 >If struct wired_map_entry is declared in wired_map.h,
 >  
 >
 >>struct wired_map_entry mip3_wired_map[MIPS3_NWIRED_ENTRY];
 >>    
 >>
 >is enough. 
 >  
 >
 That's correct.  I should have caught that.  (This is a sign that my 
 build isn't actually compiling these into the kernel -- I need to review 
 my configuration files.  I guess I need to update my PCI code to use 
 these ones.)
 
 >  
 >
 >>+boolean_t
 >>+mips3_wired_enter_page(vaddr_t va, paddr_t pa, vsize_t pgsz)
 >>    
 >>
 > :
 >  
 >
 >>+	/* make sure entries are aligned */
 >>+	KASSERT((va & (pgsize - 1)) == 0);
 >>+	KASSERT((pa & (pgsize - 1)) == 0);
 >>    
 >>
 >
 >These pgsize should be pgsz?
 >(I rename other pgsz to pgsize instead in my patch though
 >  
 >
 Whichever, it doesn't matter to me.
 
 >  
 >
 >>+	/* TLB entries come in pairs: this is the first address of the pair */
 >>+	va0 = va & ~pgsz;
 >>    
 >>
 >
 >This va0 should be double entry size aligned, i.e.
 >  
 >
 >>	va0 = va & ~(pgsz * 2 - 1);
 >>    
 >>
 >is right?
 >  
 >
 Yes.  But we have already asserted that none of the low bits are set.  
 So my original is also correct.  Your version may be clearer, but it 
 uses two additional instructions.
 
 >  
 >
 >>+mips3_wired_enter_region(vaddr_t va, paddr_t pa, vsize_t size)
 >>    
 >>
 > :
 >  
 >
 >>+	/* adjust for alignment */
 >>+	va &= ~MIPS3_WIRED_ENTRY_OFFMASK;
 >>+	pa &= ~MIPS3_WIRED_ENTRY_OFFMASK;
 >>    
 >>
 >
 >There is no MIPS3_WIRED_ENTRY_OFFMAS definition now, but 
 >MIPS3_WIRED_OFFMASK is enough for the new mips3_wired_enter_page()?
 >  
 >
 Oops!  I took it out of the header, and then forgot to rewrite the C 
 code to use the expanded macro form.  But leaving it in the header looks 
 good, too.
 
 >  
 >
 >>+		va += MIPS3_WIRED_ENTRY_SIZE;
 >>+		pa += MIPS3_WIRED_ENTRY_SIZE;
 >>    
 >>
 >
 >Maybe these should also be MIPS3_WIRED_SIZE.
 >  
 >
 Yes.
 
 >  
 >
 >>--- evbmips/include/Makefile	29 Sep 2005 16:40:06 -0000	1.1.1.1
 >>    
 >>
 > :
 >  
 >
 >>-	wchar_limits.h
 >>+	wchar_limits.h wired_map.h
 >>    
 >>
 >
 >No need to install wired_map.h to userland, I think.
 >  
 >
 Yes, that's true I suppose.
 
 >In mipsX_subr.S:MIPSX(TLBWriteIndexedVPS) (not in your latest patch):
 >- According to other TLB functions, _MFC0 and _MTC0 is not needed
 >  for STATUS, PG_MASK, and INDEX. Is it right?
 >  
 >
 Nice catch.
 
 >- I'm not sure where we should have COP_SYNC and how many extra nops
 >  are needed after tlbwi, but it won't have any bad side effects...
 >  
 >
 Seems reasonable.
 
 All in all, I'm pretty satisfied with your version of the patch.
 
     -- Garrett
 
 >---
 >Izumi Tsutsui
 >
 >
 >Index: mips/conf/files.mips
 >===================================================================
 >RCS file: /cvsroot/src/sys/arch/mips/conf/files.mips,v
 >retrieving revision 1.51
 >diff -u -r1.51 files.mips
 >--- mips/conf/files.mips	24 Jan 2005 10:03:57 -0000	1.51
 >+++ mips/conf/files.mips	3 Nov 2005 08:30:28 -0000
 >@@ -13,6 +13,7 @@
 > 					# ENABLE_MIPS_R3NKK
 > defflag	opt_mips_cache.h		MIPS3_NO_PV_UNCACHED
 > 					ENABLE_MIPS4_CACHE_R10K
 >+defflag opt_mips3_wired.h		ENABLE_MIPS3_WIRED_MAP
 > 
 > file	arch/mips/mips/locore_mips1.S		mips1
 > file	arch/mips/mips/locore_mips3.S		mips3 | mips4 | mips32 | mips64
 >@@ -37,6 +38,7 @@
 > file	arch/mips/mips/vm_machdep.c
 > file	arch/mips/mips/process_machdep.c
 > file	arch/mips/mips/cpu_exec.c
 >+file	arch/mips/mips/wired_map.c (mips3|mips4|mips32|mips64) & enable_mips3_wired_map
 > 
 > file	arch/mips/mips/cache.c
 > file	arch/mips/mips/cache_r3k.c		mips1
 >Index: mips/include/locore.h
 >===================================================================
 >RCS file: /cvsroot/src/sys/arch/mips/include/locore.h,v
 >retrieving revision 1.70
 >diff -u -r1.70 locore.h
 >--- mips/include/locore.h	30 Oct 2005 04:40:43 -0000	1.70
 >+++ mips/include/locore.h	3 Nov 2005 08:30:28 -0000
 >@@ -57,6 +57,7 @@
 > void	mips3_TBIS(vaddr_t);
 > int	mips3_TLBUpdate(u_int, u_int);
 > void	mips3_TLBRead(int, struct tlb *);
 >+void	mips3_TLBWriteIndexedVPS(int, struct tlb *);
 > void	mips3_wbflush(void);
 > void	mips3_proc_trampoline(void);
 > void	mips3_cpu_switch_resume(void);
 >@@ -69,6 +70,7 @@
 > void	mips5900_TBIS(vaddr_t);
 > int	mips5900_TLBUpdate(u_int, u_int);
 > void	mips5900_TLBRead(int, struct tlb *);
 >+void	mips5900_TLBWriteIndexedVPS(int, struct tlb *);
 > void	mips5900_wbflush(void);
 > void	mips5900_proc_trampoline(void);
 > void	mips5900_cpu_switch_resume(void);
 >@@ -83,6 +85,7 @@
 > void	mips32_TBIS(vaddr_t);
 > int	mips32_TLBUpdate(u_int, u_int);
 > void	mips32_TLBRead(int, struct tlb *);
 >+void	mips32_TLBWriteIndexedVPS(int, struct tlb *);
 > void	mips32_wbflush(void);
 > void	mips32_proc_trampoline(void);
 > void	mips32_cpu_switch_resume(void);
 >@@ -95,6 +98,7 @@
 > void	mips64_TBIS(vaddr_t);
 > int	mips64_TLBUpdate(u_int, u_int);
 > void	mips64_TLBRead(int, struct tlb *);
 >+void	mips64_TLBWriteIndexedVPS(int, struct tlb *);
 > void	mips64_wbflush(void);
 > void	mips64_proc_trampoline(void);
 > void	mips64_cpu_switch_resume(void);
 >@@ -228,6 +232,7 @@
 > #define MIPS_TBIAP()		mips3_TBIAP(mips_num_tlb_entries)
 > #define MIPS_TBIS		mips3_TBIS
 > #define MachTLBUpdate		mips3_TLBUpdate
 >+#define MachTLBWriteIndexedVPS	mips3_TLBWriteIndexedVPS
 > #define proc_trampoline		mips3_proc_trampoline
 > #define wbflush()		mips3_wbflush()
 > #elif !defined(MIPS1) && !defined(MIPS3) &&  defined(MIPS32) && !defined(MIPS64)
 >@@ -235,6 +240,7 @@
 > #define MIPS_TBIAP()		mips32_TBIAP(mips_num_tlb_entries)
 > #define MIPS_TBIS		mips32_TBIS
 > #define MachTLBUpdate		mips32_TLBUpdate
 >+#define MachTLBWriteIndexedVPS	mips32_TLBWriteIndexedVPS
 > #define proc_trampoline		mips32_proc_trampoline
 > #define wbflush()		mips32_wbflush()
 > #elif !defined(MIPS1) && !defined(MIPS3) && !defined(MIPS32) &&  defined(MIPS64)
 >@@ -243,6 +249,7 @@
 > #define MIPS_TBIAP()		mips64_TBIAP(mips_num_tlb_entries)
 > #define MIPS_TBIS		mips64_TBIS
 > #define MachTLBUpdate		mips64_TLBUpdate
 >+#define MachTLBWriteIndexedVPS	mips64_TLBWriteIndexedVPS
 > #define proc_trampoline		mips64_proc_trampoline
 > #define wbflush()		mips64_wbflush()
 > #elif !defined(MIPS1) &&  defined(MIPS3) && !defined(MIPS32) && !defined(MIPS64) && defined(MIPS3_5900)
 >@@ -250,6 +257,7 @@
 > #define MIPS_TBIAP()		mips5900_TBIAP(mips_num_tlb_entries)
 > #define MIPS_TBIS		mips5900_TBIS
 > #define MachTLBUpdate		mips5900_TLBUpdate
 >+#define MachTLBWriteIndexedVPS	mips5900_TLBWriteIndexedVPS
 > #define proc_trampoline		mips5900_proc_trampoline
 > #define wbflush()		mips5900_wbflush()
 > #else
 >Index: mips/include/mips3_pte.h
 >===================================================================
 >RCS file: /cvsroot/src/sys/arch/mips/include/mips3_pte.h,v
 >retrieving revision 1.18
 >diff -u -r1.18 mips3_pte.h
 >--- mips/include/mips3_pte.h	10 Oct 2005 02:14:43 -0000	1.18
 >+++ mips/include/mips3_pte.h	3 Nov 2005 08:30:28 -0000
 >@@ -181,6 +181,9 @@
 > #define	MIPS3_PG_SIZE_MASK_TO_SIZE(pg_mask)	\
 >     ((((pg_mask) | 0x00001fff) + 1) / 2)
 > 
 >+#define	MIPS3_PG_SIZE_TO_MASK(pg_size)		\
 >+    ((((pg_size) * 2) - 1) & ~0x00001fff)
 >+
 > /* NEC Vr41xx uses different pagemask values. */
 > #define	MIPS4100_PG_SIZE_1K	0x00000000
 > #define	MIPS4100_PG_SIZE_4K	0x00001800
 >@@ -190,3 +193,7 @@
 > 
 > #define	MIPS4100_PG_SIZE_MASK_TO_SIZE(pg_mask)	\
 >     ((((pg_mask) | 0x000007ff) + 1) / 2)
 >+
 >+#define	MIPS4100_PG_SIZE_TO_MASK(pg_size)		\
 >+    ((((pg_size) * 2) - 1) & ~0x000007ff)
 >+
 >Index: mips/mips/mipsX_subr.S
 >===================================================================
 >RCS file: /cvsroot/src/sys/arch/mips/mips/mipsX_subr.S,v
 >retrieving revision 1.17
 >diff -u -r1.17 mipsX_subr.S
 >--- mips/mips/mipsX_subr.S	8 Sep 2005 15:19:58 -0000	1.17
 >+++ mips/mips/mipsX_subr.S	3 Nov 2005 08:30:29 -0000
 >@@ -118,6 +118,7 @@
 > #include "opt_cputype.h"
 > #include "opt_ddb.h"
 > #include "opt_kgdb.h"
 >+#include "opt_mips3_wired.h"
 > 
 > #include <sys/cdefs.h>
 > 
 >@@ -1593,6 +1594,68 @@
 > 	nop
 > END(MIPSX(SetPID))
 > 
 >+#if defined(ENABLE_MIPS3_WIRED_MAP)
 >+/*--------------------------------------------------------------------------
 >+ *
 >+ * mipsN_TLBWriteIndexedVPS --
 >+ *
 >+ *      Write the given entry into the TLB at the given index.
 >+ *      Pass full R4000 style TLB info including variable page size mask.
 >+ *
 >+ *      mipsN_TLBWriteIndexed(unsigned int index, struct tlb *tlb)
 >+ *
 >+ * Results:
 >+ *      None.
 >+ *
 >+ * Side effects:
 >+ *      TLB entry set.
 >+ *
 >+ *--------------------------------------------------------------------------
 >+ */
 >+LEAF(MIPSX(TLBWriteIndexedVPS))
 >+	mfc0	v1, MIPS_COP_0_STATUS		# Save the status register.
 >+	mtc0	zero, MIPS_COP_0_STATUS		# Disable interrupts
 >+	COP0_SYNC
 >+	nop
 >+	lw	a2, 8(a1)			# fetch tlb->tlb_lo0
 >+	lw	a3, 12(a1)			# fetch tlb->tlb_lo1
 >+	mfc0	v0, MIPS_COP_0_TLB_PG_MASK	# Save current page mask.
 >+	_MFC0	t0, MIPS_COP_0_TLB_HI		# Save the current PID.
 >+
 >+	_MTC0	a2, MIPS_COP_0_TLB_LO0		# Set up entry low0.
 >+	COP0_SYNC
 >+	_MTC0	a3, MIPS_COP_0_TLB_LO1		# Set up entry low1.
 >+	COP0_SYNC
 >+	nop
 >+	lw	a2, 0(a1)			# fetch tlb->tlb_mask
 >+	lw	a3, 4(a1)			# fetch tlb->tlb_hi
 >+	nop
 >+	mtc0	a0, MIPS_COP_0_TLB_INDEX	# Set the index.
 >+	COP0_SYNC
 >+	mtc0	a2, MIPS_COP_0_TLB_PG_MASK	# Set up entry pagemask.
 >+	COP0_SYNC
 >+	_MTC0	a3, MIPS_COP_0_TLB_HI		# Set up entry high.
 >+	COP0_SYNC
 >+	nop
 >+	nop
 >+	tlbwi					# Write the TLB
 >+	COP0_SYNC
 >+	nop
 >+	nop
 >+	nop					# Delay for effect
 >+	nop
 >+
 >+	_MTC0	t0, MIPS_COP_0_TLB_HI		# Restore the PID.
 >+	COP0_SYNC
 >+	mtc0	v0, MIPS_COP_0_TLB_PG_MASK	# Restore page mask.
 >+	COP0_SYNC
 >+	nop
 >+	nop
 >+	j       ra
 >+	mtc0	v1, MIPS_COP_0_STATUS		# Restore the status register
 >+END(MIPSX(TLBWriteIndexedVPS))
 >+#endif	/* ENABLE_MIPS3_WIRED_MAP */
 >+	
 > /*--------------------------------------------------------------------------
 >  *
 >  * mipsN_TLBUpdate --
 >--- /dev/null	2005-11-03 11:53:16.000000000 +0900
 >+++ mips/include/wired_map.h	2005-11-03 11:48:22.000000000 +0900
 >@@ -0,0 +1,100 @@
 >+/*	$NetBSD$	*/
 >+
 >+/*-
 >+ * Copyright (c) 2005 Tadpole Computer Inc.
 >+ * All rights reserved.
 >+ *
 >+ * Written by Garrett D'Amore for Tadpole Computer Inc.
 >+ *
 >+ * 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. The name of Tadpole Computer Inc. may not be used to endorse
 >+ *    or promote products derived from this software without specific
 >+ *    prior written permission.
 >+ *
 >+ * THIS SOFTWARE IS PROVIDED BY TADPOLE COMPUTER INC. ``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 TADPOLE COMPUTER INC.
 >+ * 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.
 >+ */
 >+
 >+#ifndef _MIPS_WIRED_MAP_H
 >+#define _MIPS_WIRED_MAP_H
 >+
 >+/*
 >+ * Certain machines have peripheral busses which are only accessible
 >+ * using the TLB.
 >+ *
 >+ * For example, certain Alchemy parts place PCI and PCMCIA busses at
 >+ * physical address spaces which are beyond the normal 32-bit range.
 >+ * In order to access these spaces TLB entries mapping 36-bit physical
 >+ * addresses to 32-bit logical addresses must be used.
 >+ *
 >+ * Note that all wired mappings are must be 32 MB aligned.  This is
 >+ * because we use 32 MB mappings in the TLB.  Changing this might get
 >+ * us more effficent use of the address space, but it would greatly
 >+ * complicate the code, and would also probably consume additional TLB
 >+ * entries.
 >+ *
 >+ * Note that within a single 32 MB region, you can have multiple
 >+ * decoders, but they must decode uniquely within the same 32MB of
 >+ * physical address space.
 >+ *
 >+ * BEWARE: The start of KSEG2 (0xC0000000) is used by the NetBSD kernel
 >+ * for context switching and is associated with wired entry 0.  So you
 >+ * cannot use that, as I discovered the hard way.
 >+ *
 >+ * Note also that at the moment this is not supported on the MIPS-I
 >+ * ISA (but it shouldn't need it anyway.)
 >+ */
 >+
 >+#ifndef MIPS3_WIRED_SIZE
 >+#define MIPS3_WIRED_SIZE	MIPS3_PG_SIZE_MASK_TO_SIZE(MIPS3_PG_SIZE_16M)
 >+#endif
 >+#define MIPS3_WIRED_OFFMASK	(MIPS3_WIRED_SIZE - 1)
 >+
 >+/*
 >+ * This defines the maximum number of wired TLB entries that the wired
 >+ * map will be allowed to consume.  It can (and probably will!)
 >+ * consume fewer, but it will not consume more.  Note that NetBSD also
 >+ * uses one wired entry for context switching (see TLB_WIRED_UPAGES),
 >+ * and that is not included in this number.
 >+ */
 >+#ifndef MIPS3_NWIRED_ENTRY
 >+#define MIPS3_NWIRED_ENTRY	8	/* upper limit */
 >+#endif
 >+
 >+struct wired_map_entry {
 >+	paddr_t	pa0;
 >+	paddr_t	pa1;
 >+	vaddr_t	va;
 >+	vsize_t	pgmask;
 >+};
 >+
 >+extern struct wired_map_entry mips3_wired_map[];
 >+extern int mips3_nwired_page;
 >+
 >+/*
 >+ * Wire down a region of the specified size.
 >+ */
 >+boolean_t mips3_wired_enter_region(vaddr_t, paddr_t, vsize_t);
 >+
 >+/*
 >+ * Wire down a single page using specified page size.
 >+ */
 >+boolean_t mips3_wired_enter_page(vaddr_t, paddr_t, vsize_t);
 >+
 >+#endif	/* _MIPS_WIRED_MAP_H */
 >--- /dev/null	2005-11-03 11:53:16.000000000 +0900
 >+++ mips/mips/wired_map.c	2005-11-03 13:46:38.000000000 +0900
 >@@ -0,0 +1,202 @@
 >+/*	$NetBSD$	*/
 >+
 >+/*-
 >+ * Copyright (c) 2005 Tadpole Computer Inc.
 >+ * All rights reserved.
 >+ *
 >+ * Written by Garrett D'Amore for Tadpole Computer Inc.
 >+ *
 >+ * 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. The name of Tadpole Computer Inc. may not be used to endorse
 >+ *    or promote products derived from this software without specific
 >+ *    prior written permission.
 >+ *
 >+ * THIS SOFTWARE IS PROVIDED BY TADPOLE COMPUTER INC. ``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 TADPOLE COMPUTER INC.
 >+ * 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.
 >+ */ 
 >+/*
 >+ * Copyright (C) 2000 Shuichiro URATA.  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. The name of the author may not be used to endorse or promote products
 >+ *    derived from this software without specific prior written permission.
 >+ *
 >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 code is derived from similiar code in the ARC port of NetBSD, but
 >+ * it now bears little resemblence to it owing to quite different needs
 >+ * from the mapping logic.
 >+ */
 >+
 >+#include <sys/cdefs.h>
 >+__KERNEL_RCSID(0, "$NetBSD$");
 >+
 >+#include <sys/param.h>
 >+#include <sys/systm.h>
 >+#include <uvm/uvm_extern.h>
 >+#include <machine/cpu.h>
 >+#include <machine/locore.h>
 >+#include <machine/pte.h>
 >+#include <machine/vmparam.h>
 >+#include <machine/wired_map.h>
 >+
 >+#include <mips/locore.h>
 >+#include <mips/pte.h>
 >+
 >+struct wired_map_entry mips3_wired_map[MIPS3_NWIRED_ENTRY];
 >+int mips3_nwired_page;
 >+
 >+/*
 >+ * Lower layer API, to supply an explicit page size.  It only wires a
 >+ * single page at a time.
 >+ */
 >+boolean_t
 >+mips3_wired_enter_page(vaddr_t va, paddr_t pa, vsize_t pgsize)
 >+{
 >+	struct tlb tlb;
 >+	vaddr_t va0;
 >+	int found, index;
 >+
 >+	/* make sure entries are aligned */
 >+	KASSERT((va & (pgsize - 1)) == 0);
 >+	KASSERT((pa & (pgsize - 1)) == 0);
 >+
 >+	/* TLB entries come in pairs: this is the first address of the pair */
 >+	va0 = va & ~(pgsize * 2 - 1);
 >+
 >+	found = 0;
 >+	for (index = 0; index < mips3_nwired_page; index++) {
 >+		if (mips3_wired_map[index].va == va0) {
 >+			if ((va & pgsize) == 0) {
 >+				/* EntryLo0 */
 >+				mips3_wired_map[index].pa0 = pa;
 >+			} else {
 >+				/* EntryLo1 */
 >+				mips3_wired_map[index].pa1 = pa;
 >+			}
 >+			found = 1;
 >+			break;
 >+		}
 >+	}
 >+
 >+	if (found == 0) {
 >+		/* we have to allocate a new wired entry */
 >+		if (mips3_nwired_page >= MIPS3_NWIRED_ENTRY) {
 >+#ifdef DIAGNOSTIC
 >+			printf("mips3_wired_map: entries exhausted\n");
 >+#endif
 >+			return FALSE;
 >+		}
 >+
 >+		index = mips3_nwired_page;
 >+		mips3_nwired_page++;
 >+		if (va == va0) {
 >+			/* EntryLo0 */
 >+			mips3_wired_map[index].pa0 = pa;
 >+			mips3_wired_map[index].pa1 = 0;
 >+		} else {
 >+			/* EntryLo1 */
 >+			mips3_wired_map[index].pa0 = 0;
 >+			mips3_wired_map[index].pa1 = pa;
 >+		}
 >+		mips3_wired_map[index].va = va0;
 >+		mips3_wired_map[index].pgmask = MIPS3_PG_SIZE_TO_MASK(pgsize);
 >+
 >+		/* Allocate new wired entry */
 >+		mips3_cp0_wired_write(MIPS3_TLB_WIRED_UPAGES +
 >+		    mips3_nwired_page + 1);
 >+	}
 >+
 >+	/* map it */
 >+	tlb.tlb_mask = mips3_wired_map[index].pgmask;
 >+	tlb.tlb_hi = mips3_vad_to_vpn(va);
 >+	if (mips3_wired_map[index].pa0 == 0)
 >+		tlb.tlb_lo0 = MIPS3_PG_G;
 >+	else
 >+		tlb.tlb_lo0 =
 >+		    mips3_paddr_to_tlbpfn(mips3_wired_map[index].pa0) |
 >+		    MIPS3_PG_IOPAGE(
 >+			    PMAP_CCA_FOR_PA(mips3_wired_map[index].pa0));
 >+	if (mips3_wired_map[index].pa1 == 0)
 >+		tlb.tlb_lo1 = MIPS3_PG_G;
 >+	else
 >+		tlb.tlb_lo1 = mips3_paddr_to_tlbpfn(
 >+			mips3_wired_map[index].pa1) |
 >+		    MIPS3_PG_IOPAGE(
 >+			    PMAP_CCA_FOR_PA(mips3_wired_map[index].pa1));
 >+	MachTLBWriteIndexedVPS(MIPS3_TLB_WIRED_UPAGES + index, &tlb);
 >+	return TRUE;
 >+}
 >+
 >+
 >+/*
 >+ * Wire down a mapping from a virtual to physical address.  The size
 >+ * of the region must be a multiple of MIPS3_WIRED_SIZE, with
 >+ * matching alignment.
 >+ *
 >+ * Typically the caller will just pass a physaddr that is the same as
 >+ * the vaddr with bits 35-32 set nonzero.
 >+ */
 >+boolean_t
 >+mips3_wired_enter_region(vaddr_t va, paddr_t pa, vsize_t size)
 >+{
 >+	vaddr_t	vend;
 >+	/*
 >+	 * This routine allows for for wired mappings to be set up,
 >+	 * and handles previously defined mappings and mapping
 >+	 * overlaps reasonably well.  However, caution should be used
 >+	 * not to attempt to change the mapping for a page unless you
 >+	 * are certain that you are the only user of the virtual
 >+	 * address space, otherwise chaos may ensue.
 >+	 */
 >+
 >+	/* offsets within the page have to be identical */
 >+	KASSERT((va & MIPS3_WIRED_OFFMASK) == (pa & MIPS3_WIRED_OFFMASK));
 >+
 >+	vend = va + size;
 >+	/* adjust for alignment */
 >+	va &= ~MIPS3_WIRED_OFFMASK;
 >+	pa &= ~MIPS3_WIRED_OFFMASK;
 >+
 >+	while (va < vend) {
 >+		if (!mips3_wired_enter_page(va, pa, MIPS3_WIRED_SIZE))
 >+			return FALSE;
 >+		va += MIPS3_WIRED_SIZE;
 >+		pa += MIPS3_WIRED_SIZE;
 >+	}
 >+	return TRUE;
 >+}
 >  
 >