Re-factor the code in pmap_extract() that checks the 601 I/O segment

table and the BAT tables into separate functions that can be called
from outside of the pmap module.
This commit is contained in:
thorpej 2021-03-12 04:57:42 +00:00
parent 9f07171dbd
commit 6311fdd048
2 changed files with 98 additions and 52 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.h,v 1.34 2021/03/02 01:47:44 thorpej Exp $ */
/* $NetBSD: pmap.h,v 1.35 2021/03/12 04:57:42 thorpej Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -158,6 +158,13 @@ int pmap_pte_spill(pmap_t, vaddr_t, bool);
int pmap_ste_spill(pmap_t, vaddr_t, bool);
void pmap_pinit(pmap_t);
#ifdef PPC_OEA601
bool pmap_extract_ioseg601(vaddr_t, paddr_t *);
#endif /* PPC_OEA601 */
#ifdef PPC_OEA
bool pmap_extract_battable(vaddr_t, paddr_t *);
#endif /* PPC_OEA */
u_int powerpc_mmap_flags(paddr_t);
#define POWERPC_MMAP_FLAG_MASK 0xf
#define POWERPC_MMAP_FLAG_PREFETCHABLE 0x1

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.c,v 1.103 2021/03/11 04:43:47 thorpej Exp $ */
/* $NetBSD: pmap.c,v 1.104 2021/03/12 04:57:42 thorpej Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@ -63,7 +63,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.103 2021/03/11 04:43:47 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.104 2021/03/12 04:57:42 thorpej Exp $");
#define PMAP_NOOPNAMES
@ -2087,6 +2087,66 @@ pmap_remove(pmap_t pm, vaddr_t va, vaddr_t endva)
PMAP_UNLOCK();
}
#if defined(PMAP_OEA)
#ifdef PPC_OEA601
bool
pmap_extract_ioseg601(vaddr_t va, paddr_t *pap)
{
if ((MFPVR() >> 16) != MPC601)
return false;
const register_t sr = iosrtable[va >> ADDR_SR_SHFT];
if (SR601_VALID_P(sr) && SR601_PA_MATCH_P(sr, va)) {
if (pap)
*pap = va;
return true;
}
return false;
}
static bool
pmap_extract_battable601(vaddr_t va, paddr_t *pap)
{
const register_t batu = battable[va >> 23].batu;
const register_t batl = battable[va >> 23].batl;
if (BAT601_VALID_P(batl) && BAT601_VA_MATCH_P(batu, batl, va)) {
const register_t mask =
(~(batl & BAT601_BSM) << 17) & ~0x1ffffL;
if (pap)
*pap = (batl & mask) | (va & ~mask);
return true;
}
return false;
}
#endif /* PPC_OEA601 */
bool
pmap_extract_battable(vaddr_t va, paddr_t *pap)
{
#ifdef PPC_OEA601
if ((MFPVR() >> 16) == MPC601)
return pmap_extract_battable601(va, pap);
#endif /* PPC_OEA601 */
if (oeacpufeat & OEACPU_NOBAT)
return false;
const register_t batu = battable[BAT_VA2IDX(va)].batu;
if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, va)) {
const register_t batl = battable[BAT_VA2IDX(va)].batl;
const register_t mask =
(~(batu & (BAT_XBL|BAT_BL)) << 15) & ~0x1ffffL;
if (pap)
*pap = (batl & mask) | (va & ~mask);
return true;
}
return false;
}
#endif /* PMAP_OEA */
/*
* Get the physical page address for the given pmap/virtual address.
*/
@ -2099,63 +2159,42 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
PMAP_LOCK();
/*
* If this is a kernel pmap lookup, also check the battable
* and if we get a hit, translate the VA to a PA using the
* BAT entries. Don't check for VM_MAX_KERNEL_ADDRESS is
* that will wrap back to 0.
* If this is the kernel pmap, check the battable and I/O
* segments for a hit. This is done only for regions outside
* VM_MIN_KERNEL_ADDRESS-VM_MAX_KERNEL_ADDRESS.
*
* Be careful when checking VM_MAX_KERNEL_ADDRESS; you don't
* want to wrap around to 0.
*/
if (pm == pmap_kernel() &&
(va < VM_MIN_KERNEL_ADDRESS ||
(KERNEL2_SR < 15 && VM_MAX_KERNEL_ADDRESS <= va))) {
KASSERT((va >> ADDR_SR_SHFT) != USER_SR);
#if defined (PMAP_OEA)
#if defined(PMAP_OEA)
#ifdef PPC_OEA601
if ((MFPVR() >> 16) == MPC601) {
register_t batu = battable[va >> 23].batu;
register_t batl = battable[va >> 23].batl;
register_t sr = iosrtable[va >> ADDR_SR_SHFT];
if (BAT601_VALID_P(batl) &&
BAT601_VA_MATCH_P(batu, batl, va)) {
register_t mask =
(~(batl & BAT601_BSM) << 17) & ~0x1ffffL;
if (pap)
*pap = (batl & mask) | (va & ~mask);
PMAP_UNLOCK();
return true;
} else if (SR601_VALID_P(sr) &&
SR601_PA_MATCH_P(sr, va)) {
if (pap)
*pap = va;
PMAP_UNLOCK();
return true;
}
} else
#endif /* PPC_OEA601 */
{
register_t batu = battable[BAT_VA2IDX(va)].batu;
if (BAT_VALID_P(batu,0) && BAT_VA_MATCH_P(batu,va)) {
register_t batl = battable[BAT_VA2IDX(va)].batl;
register_t mask =
(~(batu & (BAT_XBL|BAT_BL)) << 15) & ~0x1ffffL;
if (pap)
*pap = (batl & mask) | (va & ~mask);
PMAP_UNLOCK();
return true;
}
}
PMAP_UNLOCK();
return false;
#elif defined (PMAP_OEA64_BRIDGE)
if (va >= SEGMENT_LENGTH)
panic("%s: pm: %s va >= SEGMENT_LENGTH, va: 0x%08lx\n",
__func__, (pm == pmap_kernel() ? "kernel" : "user"), va);
else {
if (pap)
*pap = va;
if (pmap_extract_ioseg601(va, pap)) {
PMAP_UNLOCK();
return true;
}
#elif defined (PMAP_OEA64)
}
#endif /* PPC_OEA601 */
if (pmap_extract_battable(va, pap)) {
PMAP_UNLOCK();
return true;
}
/*
* We still check the HTAB...
*/
#elif defined(PMAP_OEA64_BRIDGE)
if (va < SEGMENT_LENGTH) {
if (pap)
*pap = va;
PMAP_UNLOCK();
return true;
}
/*
* We still check the HTAB...
*/
#elif defined(PMAP_OEA64)
#error PPC_OEA64 not supported
#endif /* PPC_OEA */
}