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: 10/26/2005 16:20:02
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: 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, 27 Oct 2005 01:19:56 +0900
In article <20051025205402.7B93A63B8C2@narn.netbsd.org>
garrett_damore@tadpole.com wrote:
> Here are the diffs. Again, I've not conditionalized the inclusion of
> mips3_wired_map.c, but if folks feel strongly enough about it I can
> certainly do so.
IMO, currently only arc port uses wired map, so it might be better to
have some proper option (like options MIPS3_WIRED_MAP etc.).
> Also, the ARC port could probably make use of my logic in
> mips3_wired_map.c, but I wanted to minimize change (and I don't have an
> ARC system to test against, anyway, so all I can do is verify the compile.)
I think the MI wired map function should also handle independent
(non-contiguous) PA ranges for TLB_LO0 and TLB_LO1.
arc port requires it to map PCI memory and I/O space at the early
bootstrap stage, and it could save wired TLB entries in other case.
I also have some more quick comments:
- VA region for wired map should be defined in machine dependent
<machine/vmparam.h> and it should be managed by extent(9) etc.
- pagemask for wired maps should be defined in machine dependent headers,
or maybe it should be passed from callers.
Currently I use the attached wired_map.[ch] for ews4800mips ports,
though it lacks some sanity checks and unmap (or remap) functions.
Maybe we should discuss more about APIs for these wired map functions.
---
Izumi Tsutsui
---
/* $NetBSD$ */
/*-
* Copyright (C) 2005 Izumi Tsutsui.
* 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.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/extent.h>
#include <uvm/uvm_extern.h>
#include <mips/pte.h>
#include <machine/locore.h>
#include <machine/vmparam.h>
#include <ews4800mips/ews4800mips/wired_map.h>
#define EWS4800MIPS_TLB_WIRED_ENTRIES 8 /* upper limit */
static int ews4800mips_enter_wired(vaddr_t va, paddr_t pa0, paddr_t pa1,
uint32_t pg_size);
static struct wired_map_entry {
paddr_t pa0;
paddr_t pa1;
vsize_t size;
vaddr_t va;
} wired_map[EWS4800MIPS_TLB_WIRED_ENTRIES];
static int nwired;
static struct extent *wired_map_ex;
static long wired_map_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
void
ews4800mips_init_wired_map(void)
{
nwired = 0;
wired_map_ex = extent_create("wired_map",
VM_MIN_WIRED_MAP_ADDRESS, VM_MAX_WIRED_MAP_ADDRESS, M_DEVBUF,
(void *)wired_map_ex_storage, sizeof(wired_map_ex_storage),
EX_NOWAIT);
if (wired_map_ex == NULL)
panic("ews4800mips_init_wired_map: can't create extent");
}
static int
ews4800mips_enter_wired(vaddr_t va, paddr_t pa0, paddr_t pa1, uint32_t pg_size)
{
struct tlb tlb;
psize_t size;
if (nwired >= EWS4800MIPS_TLB_WIRED_ENTRIES) {
#ifdef DIAGNOSTIC
printf("ews4800mips_enter_wired: wired entry exausted.\n");
#endif
return ENOMEM;
}
size = MIPS3_PG_SIZE_MASK_TO_SIZE(pg_size);
va = (va + (size - 1)) & ~(size - 1);
wired_map[nwired].va = va;
wired_map[nwired].pa0 = pa0;
wired_map[nwired].pa1 = pa1;
wired_map[nwired].size = size;
/* Allocate new wired entry */
mips3_cp0_wired_write(MIPS3_TLB_WIRED_UPAGES + nwired + 1);
/* Map to it */
tlb.tlb_mask = pg_size;
tlb.tlb_hi = mips3_vad_to_vpn(va);
if (pa0 == 0)
tlb.tlb_lo0 = MIPS3_PG_G;
else
tlb.tlb_lo0 = mips3_paddr_to_tlbpfn(pa0) | \
MIPS3_PG_IOPAGE(PMAP_CCA_FOR_PA(pa0));
if (pa1 == 0)
tlb.tlb_lo1 = MIPS3_PG_G;
else
tlb.tlb_lo1 = mips3_paddr_to_tlbpfn(pa1) | \
MIPS3_PG_IOPAGE(PMAP_CCA_FOR_PA(pa1));
mips3_TLBWriteIndexedVPS(MIPS3_TLB_WIRED_UPAGES + nwired, &tlb);
nwired++;
return 0;
}
/* Allocate new wired entries */
int
ews4800mips_map_wired(vaddr_t va, paddr_t pa0, paddr_t pa1, uint32_t pg_size)
{
psize_t size;
int error;
size = MIPS3_PG_SIZE_MASK_TO_SIZE(pg_size);
va = (va + (size - 1)) & ~(size - 1);
if (va < VM_MIN_WIRED_MAP_ADDRESS ||
va + size > VM_MAX_WIRED_MAP_ADDRESS) {
#ifdef DIAGNOSTIC
printf("ews4800mips_enter_wired: invalid va range.\n");
#endif
return EINVAL;
}
error = extent_alloc_region(wired_map_ex, va, size, EX_NOWAIT);
if (error) {
#ifdef DIAGNOSTIC
printf("ews4800mips_enter_wired: cannot allocate region.\n");
#endif
return error;
}
error = ews4800mips_enter_wired(va, pa0, pa1, pg_size);
return error;
}
vaddr_t
ews4800mips_map_wired_region(paddr_t pa, int size, uint32_t pg_mask)
{
vaddr_t va, rva;
vsize_t off;
psize_t pg_size;
int error;
pg_size = MIPS3_PG_SIZE_MASK_TO_SIZE(pg_mask);
off = pa & WIRED_ENTRY_OFFMASK(pg_size);
pa &= ~(paddr_t)WIRED_ENTRY_OFFMASK(pg_size);
size += off;
if ((size + WIRED_ENTRY_SIZE(pg_size) - 1) / WIRED_ENTRY_SIZE(pg_size) >
EWS4800MIPS_TLB_WIRED_ENTRIES - nwired) {
#ifdef DIAGNOSTIC
printf("ews4800mips_map_wired_region(0x%lx, 0x%lx)"
": %d is not enough\n", pa + off, size - off,
EWS4800MIPS_TLB_WIRED_ENTRIES - nwired);
#endif
return 0; /* free wired TLB is not enough */
}
error = extent_alloc(wired_map_ex, size, WIRED_ENTRY_SIZE(pg_size), 0,
EX_NOWAIT, &va);
if (error) {
#ifdef DIAGNOSTIC
printf("ews4800mips_map_wired_region: can't allocate region\n");
#endif
return 0;
}
rva = va;
while (size > 0) {
ews4800mips_enter_wired(va, pa, pa + pg_size, pg_mask);
pa += WIRED_ENTRY_SIZE(pg_size);
va += WIRED_ENTRY_SIZE(pg_size);
size -= WIRED_ENTRY_SIZE(pg_size);
}
return rva + off;
}
---
---
/* $NetBSD$ */
/*-
* Copyright (C) 2005 Izumi Tsutsui.
* 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.
*/
#define WIRED_ENTRY_SIZE(pg_size) ((pg_size) * 2)
#define WIRED_ENTRY_OFFMASK(pg_size) (WIRED_ENTRY_SIZE(pg_size) - 1)
void ews4800mips_init_wired_map(void);
int ews4800mips_map_wired(vaddr_t va, paddr_t pa0, paddr_t pa1,
uint32_t pg_size);
vaddr_t ews4800mips_map_wired_region(paddr_t pa, int size, uint32_t pg_size);
---