Subject: Re: port-mips/31915: provide centralized wired_map logic
To: Garrett D'Amore <garrett_damore@tadpole.com>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: port-mips
Date: 11/01/2005 17:06:23
This is a multi-part message in MIME format.
--------------040809070208080800020000
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Well, I've decided that the right answer was to modify 
mips3_wire_down_page to support a variable mask.  Note that this API 
should only be called by lower level code that understands the implications.

To set up a full TLB the MD code will have to call this routine once 
each for PA0 and PA1.  Slightly less efficient, but it shouldn't be done 
often.  One advantage of this is that it is legal to use this to 
*change* the mapping of a wired address.

By comparision, mips3_wire_down (with the _page) suffix, is the 
preferred entry point and it keeps the caller from haviing to worry 
about the page size.

Also, there was a problem where I didn't deal with even vs. odd pages 
properly.  I've fixed that.

Finally, this includes the fix to support machine dependent page masks.

Diffs are attached...

    -- Garrett

Garrett D'Amore wrote:

> SODA Noriyuki wrote:
>
>>
>> It's OK that upper layer routine like arc/wired_map.c:arc_map_wired()
>> or port-mips/31915:mips3_wire_down() use fixed page size.
>> But primitive routine like arc/wired_map.c:arc_enter_wired() or
>> port-mips/31915:mips3_wire_down_page() should have page size
>> and (pa0 + pa1) as its arguments.
>>  
>>
>
> I think we're in violent agreement here. :-)
> I'll add a primitive function as requested.  It will indeed take all 
> of the TLB  arguments.  And it needs to be done so that it updates the 
> nwired to coexist peacefully with mips3_wire_down(), so I really do 
> have to add it to the MI code.
>
> I'll send a diff shortly.
>
>    -- Garrett
>
>> -- 
>> soda
>>  
>>


--------------040809070208080800020000
Content-Type: text/plain;
 name="wired-diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="wired-diff"

Index: sys/arch/mips/mips/mips3_wired_map.c
===================================================================
RCS file: sys/arch/mips/mips/mips3_wired_map.c
diff -N sys/arch/mips/mips/mips3_wired_map.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/arch/mips/mips/mips3_wired_map.c	2 Nov 2005 01:06:10 -0000
@@ -0,0 +1,194 @@
+/*	$NetBSD: wired_map.c,v 1.8 2005/01/22 07:35:33 tsutsui Exp $	*/
+
+/*-
+ * 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 <mips/wired_map.h>
+
+static struct wired_map_entry {
+	paddr_t	pa0;
+	paddr_t	pa1;
+	vaddr_t	va;
+	vsize_t	pgmask;
+} wired_map[MIPS3_WIRED_ENTRIES];
+
+static boolean_t mips3_wire_down_page(vaddr_t va, paddr_t pa);
+static int	nwired;
+
+boolean_t
+mips3_wire_down_page(vaddr_t va, paddr_t pa, vsize_t pgsz)
+{
+	struct tlb	tlb;
+	int		index;
+	int		found = 0;
+	vaddr_t		va0;
+
+	if ((va & (pgsz - 1)) || (pa & (pgsz - 1)))
+		panic("mips3_wire_down_page: not aligned");
+
+	/* TLB entries come in pairs: this is the first address of the pair */
+	va0 = va & ~pgsz;
+
+	for (index = 0; index < nwired; index++) {
+		if (wired_map[index].va == va0) {
+			if ((va & pgsz) == 0) {
+				/* EntryLo0 */
+				wired_map[index].pa0 = pa;
+				found++;
+				break;
+			} else {
+				/* EntryLo1 */
+				wired_map[index].pa1 = pa;
+				found++;
+				break;
+			}
+		}
+	}
+
+	if (found == 0) {
+		/* we have to allocate a new wired entry */
+		if (nwired >= MIPS3_WIRED_ENTRIES)
+			return 0;
+		index = nwired;
+		nwired++;
+		if (va == va0) {
+			/* EntryLo0 */
+			wired_map[index].pa0 = pa;
+			wired_map[index].pa1 = 0;
+		} else {
+			/* EntryLo1 */
+			wired_map[index].pa0 = 0;
+			wired_map[index].pa1 = pa;
+		}
+		wired_map[index].va = va0;
+		wired_map[index].pgmask = MIPS3_PG_SIZE_TO_MASK(pgsz);
+
+		/* Allocate new wired entry */
+		mips3_cp0_wired_write(MIPS3_TLB_WIRED_UPAGES + nwired + 1);
+	}
+
+	/* map it */
+	tlb.tlb_mask = wired_map[index].pgmask;
+	tlb.tlb_hi = mips3_vad_to_vpn(va);
+	if (wired_map[index].pa0 == 0)
+		tlb.tlb_lo0 = MIPS3_PG_G;
+	else
+		tlb.tlb_lo0 = mips3_paddr_to_tlbpfn(wired_map[index].pa0) |
+		    MIPS3_PG_IOPAGE(PMAP_CCA_FOR_PA(wired_map[index].pa0));
+	if (wired_map[index].pa1 == 0)
+		tlb.tlb_lo1 = MIPS3_PG_G;
+	else
+		tlb.tlb_lo1 = mips3_paddr_to_tlbpfn(wired_map[index].pa1) |
+		    MIPS3_PG_IOPAGE(PMAP_CCA_FOR_PA(wired_map[index].pa1));
+	MachTLBWriteIndexedVPS(MIPS3_TLB_WIRED_UPAGES + index, &tlb);
+	return 1;
+}
+
+
+/*
+ * Wire down pages.  Returns the actual size wired down, as we may
+ * have to wire down more memory than that.  In general, we always
+ * wire down 16 MB at a time, to simplify the logic.
+ *
+ * Typically the caller will just pass a physaddr that is the same as
+ * the vaddr with bits 35-32 set nonzero.
+ */
+boolean_t
+mips3_wire_down(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 */
+	if ((va & MIPS3_WIRED_OFFMASK) != (pa & MIPS3_WIRED_OFFMASK))
+		panic("mips3_wire_down: mismatched offsets!");
+
+	vend = va + size;
+	/* adjust for alignment */
+	va &= ~MIPS3_WIRED_ENTRY_OFFMASK;
+	pa &= ~MIPS3_WIRED_ENTRY_OFFMASK;
+
+	while (va < vend) {
+		if (!mips3_wire_down_page(va, pa, MIPS3_WIRED_ENTRY_SIZE))
+			return 0;
+		va += MIPS3_WIRED_ENTRY_SIZE;
+		pa += MIPS3_WIRED_ENTRY_SIZE;
+	}
+	return 1;
+}
Index: sys/arch/mips/include/wired_map.h
===================================================================
RCS file: sys/arch/mips/include/wired_map.h
diff -N sys/arch/mips/include/wired_map.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/arch/mips/include/wired_map.h	2 Nov 2005 01:06:10 -0000
@@ -0,0 +1,94 @@
+/*	$NetBSD: wired_map.h,v 1.2 2005/01/22 07:35:33 tsutsui Exp $	*/
+
+/*-
+ * 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.)
+ */
+#define	MIPS3_SIZE_TO_PG_MASK(x)	(((x * 2) - 1) & ~0x1fff)
+
+#ifndef MIPS3_WIRED_SIZE
+#define	MIPS3_WIRED_SIZE	MIPS3_PG_SIZE_MASK_TO_SIZE(MIPS_PG_SIZE_16M)
+#endif
+
+/*
+ * 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_WIRED_ENTRIES
+#define MIPS3_WIRED_ENTRIES	8	/* upper limit */
+#endif	/* MIPS3_WIRED_ENTRIES */
+
+
+/*
+ * Wire down a mapping from a virtual to physical address.  The size
+ * of the region must be a multiple of MIPS3_WIRED_ENTRY_SIZE, with
+ * matching alignment.
+ */
+boolean_t mips3_wire_down(vaddr_t, paddr_t, vsize_t);
+
+/*
+ * Lower layer API, to supply an explicit page size.  It only wires a
+ * single page at a time.
+ */
+boolean_t mips3_wire_down_page(vaddr_t, paddr_t, vsize_t);
+
+#endif	/* _MIPS_WIRED_MAP_H */
Index: sys/arch/mips/include/mips3_pte.h
===================================================================
RCS file: /net/projects/meteor/cvs/netbsd/src/sys/arch/mips/include/mips3_pte.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 mips3_pte.h
--- sys/arch/mips/include/mips3_pte.h	17 Oct 2005 16:48:25 -0000	1.1.1.2
+++ sys/arch/mips/include/mips3_pte.h	2 Nov 2005 01:06:10 -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)
+

--------------040809070208080800020000--