* ppc4xx_tlb_reserve(): allocate "reserved" TLB entries dynamically
* ppc4xx_tlb_mapiodev(): resolve pa to va from reserved TLB entries OK by matt@ XXX we'll keep TLB_NRESERVED defined until we fix explora to use new API
This commit is contained in:
parent
037fe176f0
commit
ca97defaa7
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmap.c,v 1.41 2006/07/12 06:22:17 simonb Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.42 2006/08/31 22:13:51 freza Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2001 Wasabi Systems, Inc.
|
||||
|
@ -67,7 +67,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.41 2006/07/12 06:22:17 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.42 2006/08/31 22:13:51 freza Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
|
@ -96,12 +96,14 @@ caddr_t kernmap;
|
|||
|
||||
#define MINCTX 2
|
||||
#define NUMCTX 256
|
||||
|
||||
volatile struct pmap *ctxbusy[NUMCTX];
|
||||
|
||||
#define TLBF_USED 0x1
|
||||
#define TLBF_REF 0x2
|
||||
#define TLBF_LOCKED 0x4
|
||||
#define TLB_LOCKED(i) (tlb_info[(i)].ti_flags & TLBF_LOCKED)
|
||||
|
||||
typedef struct tlb_info_s {
|
||||
char ti_flags;
|
||||
char ti_ctx; /* TLB_PID assiciated with the entry */
|
||||
|
@ -110,7 +112,10 @@ typedef struct tlb_info_s {
|
|||
|
||||
volatile tlb_info_t tlb_info[NTLB];
|
||||
/* We'll use a modified FIFO replacement policy cause it's cheap */
|
||||
volatile int tlbnext = TLB_NRESERVED;
|
||||
volatile int tlbnext;
|
||||
|
||||
static int tlb_nreserved = 0;
|
||||
static int pmap_bootstrap_done = 0;
|
||||
|
||||
/* Event counters */
|
||||
struct evcnt tlbmiss_ev = EVCNT_INITIALIZER(EVCNT_TYPE_TRAP,
|
||||
|
@ -151,6 +156,18 @@ struct pv_entry {
|
|||
struct pmap *pv_pm;
|
||||
};
|
||||
|
||||
/* Each index corresponds to TLB_SIZE_* value. */
|
||||
static size_t tlbsize[] = {
|
||||
1024, /* TLB_SIZE_1K */
|
||||
4096, /* TLB_SIZE_4K */
|
||||
16384, /* TLB_SIZE_16K */
|
||||
65536, /* TLB_SIZE_64K */
|
||||
262144, /* TLB_SIZE_256K */
|
||||
1048576, /* TLB_SIZE_1M */
|
||||
4194304, /* TLB_SIZE_4M */
|
||||
16777216, /* TLB_SIZE_16M */
|
||||
};
|
||||
|
||||
struct pv_entry *pv_table;
|
||||
static struct pool pv_pool;
|
||||
|
||||
|
@ -167,6 +184,8 @@ static inline int pte_enter(struct pmap *, vaddr_t, u_int);
|
|||
static inline int pmap_enter_pv(struct pmap *, vaddr_t, paddr_t, boolean_t);
|
||||
static void pmap_remove_pv(struct pmap *, vaddr_t, paddr_t);
|
||||
|
||||
static int ppc4xx_tlb_size_mask(size_t, int *, int *);
|
||||
|
||||
|
||||
inline struct pv_entry *
|
||||
pa_to_pv(paddr_t pa)
|
||||
|
@ -248,6 +267,12 @@ pmap_bootstrap(u_int kernelstart, u_int kernelend)
|
|||
int cnt, i;
|
||||
u_int s, e, sz;
|
||||
|
||||
/* XXXfreza: compat, we used to statically reserve 4 entries. */
|
||||
if (tlb_nreserved == 0)
|
||||
tlb_nreserved = TLB_NRESERVED;
|
||||
|
||||
tlbnext = tlb_nreserved;
|
||||
|
||||
/*
|
||||
* Allocate the kernel page table at the end of
|
||||
* kernel space so it's in the locked TTE.
|
||||
|
@ -391,11 +416,12 @@ pmap_bootstrap(u_int kernelstart, u_int kernelend)
|
|||
pmap_kernel()->pm_ctx = KERNEL_PID;
|
||||
nextavail = avail->start;
|
||||
|
||||
|
||||
evcnt_attach_static(&tlbmiss_ev);
|
||||
evcnt_attach_static(&tlbhit_ev);
|
||||
evcnt_attach_static(&tlbflush_ev);
|
||||
evcnt_attach_static(&tlbenter_ev);
|
||||
|
||||
pmap_bootstrap_done = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1244,7 +1270,7 @@ ppc4xx_tlb_find_victim(void)
|
|||
|
||||
for (;;) {
|
||||
if (++tlbnext >= NTLB)
|
||||
tlbnext = TLB_NRESERVED;
|
||||
tlbnext = tlb_nreserved;
|
||||
flags = tlb_info[tlbnext].ti_flags;
|
||||
if (!(flags & TLBF_USED) ||
|
||||
(flags & (TLBF_LOCKED | TLBF_REF)) == 0) {
|
||||
|
@ -1287,7 +1313,7 @@ ppc4xx_tlb_enter(int ctx, vaddr_t va, u_int pte)
|
|||
idx = ppc4xx_tlb_find_victim();
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((idx < TLB_NRESERVED) || (idx >= NTLB)) {
|
||||
if ((idx < tlb_nreserved) || (idx >= NTLB)) {
|
||||
panic("ppc4xx_tlb_enter: replacing entry %ld", idx);
|
||||
}
|
||||
#endif
|
||||
|
@ -1323,7 +1349,7 @@ ppc4xx_tlb_init(void)
|
|||
int i;
|
||||
|
||||
/* Mark reserved TLB entries */
|
||||
for (i = 0; i < TLB_NRESERVED; i++) {
|
||||
for (i = 0; i < tlb_nreserved; i++) {
|
||||
tlb_info[i].ti_flags = TLBF_LOCKED | TLBF_USED;
|
||||
tlb_info[i].ti_ctx = KERNEL_PID;
|
||||
}
|
||||
|
@ -1340,6 +1366,109 @@ ppc4xx_tlb_init(void)
|
|||
:: "K"(SPR_ZPR), "r" (0x1b000000));
|
||||
}
|
||||
|
||||
/*
|
||||
* ppc4xx_tlb_size_mask:
|
||||
*
|
||||
* Roundup size to supported page size, return TLBHI mask and real size.
|
||||
*/
|
||||
static int
|
||||
ppc4xx_tlb_size_mask(size_t size, int *mask, int *rsiz)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < __arraycount(tlbsize); i++)
|
||||
if (size <= tlbsize[i]) {
|
||||
*mask = (i << TLB_SIZE_SHFT);
|
||||
*rsiz = tlbsize[i];
|
||||
return (0);
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* ppc4xx_tlb_mapiodev:
|
||||
*
|
||||
* Lookup virtual address of mapping previously entered via
|
||||
* ppc4xx_tlb_reserve. Search TLB directly so that we don't
|
||||
* need to waste extra storage for reserved mappings. Note
|
||||
* that reading TLBHI also sets PID, but all reserved mappings
|
||||
* use KERNEL_PID, so the side effect is nil.
|
||||
*/
|
||||
void *
|
||||
ppc4xx_tlb_mapiodev(paddr_t base, psize_t len)
|
||||
{
|
||||
paddr_t pa;
|
||||
vaddr_t va;
|
||||
u_int lo, hi, sz;
|
||||
int i;
|
||||
|
||||
/* tlb_nreserved is only allowed to grow, so this is safe. */
|
||||
for (i = 0; i < tlb_nreserved; i++) {
|
||||
__asm volatile (
|
||||
" tlbre %0,%2,1 \n" /* TLBLO */
|
||||
" tlbre %1,%2,0 \n" /* TLBHI */
|
||||
: "=&r" (lo), "=&r" (hi)
|
||||
: "r" (i));
|
||||
|
||||
KASSERT(hi & TLB_VALID);
|
||||
KASSERT(mfspr(SPR_PID) == KERNEL_PID);
|
||||
|
||||
pa = (lo & TLB_RPN_MASK);
|
||||
if (base < pa)
|
||||
continue;
|
||||
|
||||
sz = tlbsize[(hi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT];
|
||||
if ((base + len) > (pa + sz))
|
||||
continue;
|
||||
|
||||
va = (hi & TLB_EPN_MASK) + (base & (sz - 1)); /* sz = 2^n */
|
||||
return (void *)(va);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* ppc4xx_tlb_reserve:
|
||||
*
|
||||
* Map physical range to kernel virtual chunk via reserved TLB entry.
|
||||
*/
|
||||
void
|
||||
ppc4xx_tlb_reserve(paddr_t pa, vaddr_t va, size_t size, int flags)
|
||||
{
|
||||
u_int lo, hi;
|
||||
int szmask, rsize;
|
||||
|
||||
/* Called before pmap_bootstrap(), va outside kernel space. */
|
||||
KASSERT(va < VM_MIN_KERNEL_ADDRESS || va >= VM_MAX_KERNEL_ADDRESS);
|
||||
KASSERT(! pmap_bootstrap_done);
|
||||
KASSERT(tlb_nreserved < NTLB);
|
||||
|
||||
/* Resolve size. */
|
||||
if (ppc4xx_tlb_size_mask(size, &szmask, &rsize) != 0)
|
||||
panic("ppc4xx_tlb_reserve: entry %d, %zuB too large",
|
||||
size, tlb_nreserved);
|
||||
|
||||
/* Real size will be power of two >= 1024, so this is OK. */
|
||||
pa &= ~(rsize - 1); /* RPN */
|
||||
va &= ~(rsize - 1); /* EPN */
|
||||
|
||||
lo = pa | TLB_WR | flags;
|
||||
hi = va | TLB_VALID | szmask | KERNEL_PID;
|
||||
|
||||
#ifdef PPC_4XX_NOCACHE
|
||||
lo |= TLB_I;
|
||||
#endif
|
||||
|
||||
__asm volatile(
|
||||
" tlbwe %1,%0,1 \n" /* write TLBLO */
|
||||
" tlbwe %2,%0,0 \n" /* write TLBHI */
|
||||
" sync \n"
|
||||
" isync \n"
|
||||
: : "r" (tlb_nreserved), "r" (lo), "r" (hi));
|
||||
|
||||
tlb_nreserved++;
|
||||
}
|
||||
|
||||
/*
|
||||
* We should pass the ctx in from trap code.
|
||||
|
@ -1388,7 +1517,7 @@ ctx_flush(int cnum)
|
|||
int i;
|
||||
|
||||
/* We gotta steal this context */
|
||||
for (i = TLB_NRESERVED; i < NTLB; i++) {
|
||||
for (i = tlb_nreserved; i < NTLB; i++) {
|
||||
if (tlb_info[i].ti_ctx == cnum) {
|
||||
/* Can't steal ctx if it has a locked entry. */
|
||||
if (TLB_LOCKED(i)) {
|
||||
|
@ -1403,7 +1532,7 @@ ctx_flush(int cnum)
|
|||
return (1);
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
if (i < TLB_NRESERVED)
|
||||
if (i < tlb_nreserved)
|
||||
panic("TLB entry %d not locked", i);
|
||||
#endif
|
||||
/* Invalidate particular TLB entry regardless of locked status */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tlb.h,v 1.2 2006/07/12 06:22:17 simonb Exp $ */
|
||||
/* $NetBSD: tlb.h,v 1.3 2006/08/31 22:13:51 freza Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2001 Wasabi Systems, Inc.
|
||||
|
@ -102,11 +102,13 @@ void ppc4xx_tlb_flush(vaddr_t, int);
|
|||
void ppc4xx_tlb_flush_all(void);
|
||||
void ppc4xx_tlb_init(void);
|
||||
int ppc4xx_tlb_new_pid(struct pmap *);
|
||||
void ppc4xx_tlb_reserve(paddr_t, vaddr_t, size_t, int);
|
||||
void *ppc4xx_tlb_mapiodev(paddr_t, psize_t);
|
||||
|
||||
#endif
|
||||
|
||||
#define TLB_PID_INVALID 0xFFFF
|
||||
|
||||
#define TLB_NRESERVED 4 /* Reserve 4 TLB entries for kernel */
|
||||
#define TLB_NRESERVED 4 /* XXXfreza: kill. */
|
||||
|
||||
#endif /* _IBM4XX_TLB_H_ */
|
||||
|
|
Loading…
Reference in New Issue