Subject: Re: port-mips/31915: provide centralized wired_map logic
To: None <tsutsui@netbsd.org, gnats-admin@netbsd.org,>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 11/03/2005 12:37:04
The following reply was made to PR port-mips/31915; it has been noted by GNATS.

From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
To: garrett_damore@tadpole.com
Cc: soda@sra.co.jp, gnats-bugs@NetBSD.org, port-mips@NetBSD.org,
	tsutsui@ceres.dti.ne.jp
Subject: Re: port-mips/31915: provide centralized wired_map logic
Date: Thu, 3 Nov 2005 21:36:53 +0900

 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)
 
 > 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. 
 
 > +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)
 
 > +	/* 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?
 
 > +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()?
 
 > +		va += MIPS3_WIRED_ENTRY_SIZE;
 > +		pa += MIPS3_WIRED_ENTRY_SIZE;
 
 Maybe these should also be MIPS3_WIRED_SIZE.
 
 > --- 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.
 
 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?
 - 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...
 ---
 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;
 +}