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;
+}