summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjchandra <jchandra@FreeBSD.org>2010-07-08 14:49:55 +0000
committerjchandra <jchandra@FreeBSD.org>2010-07-08 14:49:55 +0000
commit5be567ad5ff8f316da952b9fbb9352193137f28a (patch)
tree410b08c5351bfcac4a2c92c1c71b0daf33c66846
parent4e687ef5c7e93f46480469e803cc4911c39d8254 (diff)
downloadFreeBSD-src-5be567ad5ff8f316da952b9fbb9352193137f28a.zip
FreeBSD-src-5be567ad5ff8f316da952b9fbb9352193137f28a.tar.gz
Merge jmallett@'s n64 work into HEAD - changeset 8
Updated PTE/PDE macros from http://svn.freebsd.org/base/user/jmallett/octeon Introduce pmap_segshift() macro, use pmap_segmap() in place of pmap_pde, and remove pmap_pde(). Approved by: rrs (mentor) Obtained from: jmallett@
-rw-r--r--sys/mips/include/pmap.h2
-rw-r--r--sys/mips/include/pte.h17
-rw-r--r--sys/mips/mips/pmap.c53
3 files changed, 41 insertions, 31 deletions
diff --git a/sys/mips/include/pmap.h b/sys/mips/include/pmap.h
index f2ff691..3e7b937 100644
--- a/sys/mips/include/pmap.h
+++ b/sys/mips/include/pmap.h
@@ -50,7 +50,6 @@
#include <machine/pte.h>
#define NKPT 120 /* actual number of kernel page tables */
-#define NUSERPGTBLS (VM_MAXUSER_ADDRESS >> SEGSHIFT)
#ifndef LOCORE
@@ -97,7 +96,6 @@ typedef struct pmap *pmap_t;
#ifdef _KERNEL
pt_entry_t *pmap_pte(pmap_t, vm_offset_t);
-pd_entry_t pmap_segmap(pmap_t pmap, vm_offset_t va);
vm_offset_t pmap_kextract(vm_offset_t va);
#define vtophys(va) pmap_kextract(((vm_offset_t) (va)))
diff --git a/sys/mips/include/pte.h b/sys/mips/include/pte.h
index 7a05367..a767b04 100644
--- a/sys/mips/include/pte.h
+++ b/sys/mips/include/pte.h
@@ -29,6 +29,12 @@
#ifndef _MACHINE_PTE_H_
#define _MACHINE_PTE_H_
+#ifndef _LOCORE
+/* pt_entry_t is 32 bit for now, has to be made 64 bit for n64 */
+typedef uint32_t pt_entry_t;
+typedef pt_entry_t *pd_entry_t;
+#endif
+
/*
* TLB and PTE management. Most things operate within the context of
* EntryLo0,1, and begin with TLBLO_. Things which work with EntryHi
@@ -65,25 +71,20 @@
#define TLBLO_PTE_TO_PA(pte) (TLBLO_PFN_TO_PA(TLBLO_PTE_TO_PFN((pte))))
/*
+ * XXX This comment is not correct for anything more modern than R4K.
+ *
* VPN for EntryHi register. Upper two bits select user, supervisor,
* or kernel. Bits 61 to 40 copy bit 63. VPN2 is bits 39 and down to
* as low as 13, down to PAGE_SHIFT, to index 2 TLB pages*. From bit 12
* to bit 8 there is a 5-bit 0 field. Low byte is ASID.
*
+ * XXX This comment is not correct for FreeBSD.
* Note that in FreeBSD, we map 2 TLB pages is equal to 1 VM page.
*/
#define TLBHI_ASID_MASK (0xff)
#define TLBHI_PAGE_MASK (2 * PAGE_SIZE - 1)
#define TLBHI_ENTRY(va, asid) (((va) & ~TLBHI_PAGE_MASK) | ((asid) & TLBHI_ASID_MASK))
-#ifndef _LOCORE
-typedef uint32_t pt_entry_t;
-typedef pt_entry_t *pd_entry_t;
-#endif
-
-#define PDESIZE sizeof(pd_entry_t) /* for assembly files */
-#define PTESIZE sizeof(pt_entry_t) /* for assembly files */
-
/*
* TLB flags managed in hardware:
* C: Cache attribute.
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index a529254..2765fda 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -118,14 +118,25 @@ __FBSDID("$FreeBSD$");
/*
* Get PDEs and PTEs for user/kernel address space
+ *
+ * XXX The & for pmap_segshift() is wrong, as is the fact that it doesn't
+ * trim off gratuitous bits of the address space. By having the &
+ * there, we break defining NUSERPGTBLS below because the address space
+ * is defined such that it ends immediately after NPDEPG*NPTEPG*PAGE_SIZE,
+ * so we end up getting NUSERPGTBLS of 0.
*/
-#define pmap_pde(m, v) (&((m)->pm_segtab[(vm_offset_t)(v) >> SEGSHIFT]))
-#define segtab_pde(m, v) (m[(vm_offset_t)(v) >> SEGSHIFT])
+#define pmap_segshift(v) (((v) >> SEGSHIFT) & (NPDEPG - 1))
+#define segtab_pde(m, v) ((m)[pmap_segshift((v))])
-#define MIPS_SEGSIZE (1L << SEGSHIFT)
-#define mips_segtrunc(va) ((va) & ~(MIPS_SEGSIZE-1))
+#define NUSERPGTBLS (pmap_segshift(VM_MAXUSER_ADDRESS))
+#define mips_segtrunc(va) ((va) & ~SEGOFSET)
#define is_kernel_pmap(x) ((x) == kernel_pmap)
-#define vad_to_pte_offset(adr) (((adr) >> PAGE_SHIFT) & (NPTEPG -1))
+
+/*
+ * Given a virtual address, get the offset of its PTE within its page
+ * directory page.
+ */
+#define PDE_OFFSET(va) (((vm_offset_t)(va) >> PAGE_SHIFT) & (NPTEPG - 1))
struct pmap kernel_pmap_store;
pd_entry_t *kernel_segmap;
@@ -246,13 +257,13 @@ static struct local_sysmaps sysmap_lmem[MAXCPU];
sysm->valid2 = 0; \
intr_restore(intr)
-pd_entry_t
+static inline pt_entry_t *
pmap_segmap(pmap_t pmap, vm_offset_t va)
{
- if (pmap->pm_segtab)
- return (pmap->pm_segtab[((vm_offset_t)(va) >> SEGSHIFT)]);
+ if (pmap->pm_segtab != NULL)
+ return (segtab_pde(pmap->pm_segtab, va));
else
- return ((pd_entry_t)0);
+ return (NULL);
}
/*
@@ -267,9 +278,9 @@ pmap_pte(pmap_t pmap, vm_offset_t va)
pt_entry_t *pdeaddr;
if (pmap) {
- pdeaddr = (pt_entry_t *)pmap_segmap(pmap, va);
+ pdeaddr = pmap_segmap(pmap, va);
if (pdeaddr) {
- return pdeaddr + vad_to_pte_offset(va);
+ return pdeaddr + PDE_OFFSET(va);
}
}
return ((pt_entry_t *)0);
@@ -878,12 +889,12 @@ pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte)
return (0);
if (mpte == NULL) {
- ptepindex = (va >> SEGSHIFT);
+ ptepindex = pmap_segshift(va);
if (pmap->pm_ptphint &&
(pmap->pm_ptphint->pindex == ptepindex)) {
mpte = pmap->pm_ptphint;
} else {
- pteva = *pmap_pde(pmap, va);
+ pteva = pmap_segmap(pmap, va);
mpte = PHYS_TO_VM_PAGE(MIPS_KSEG0_TO_PHYS(pteva));
pmap->pm_ptphint = mpte;
}
@@ -1082,7 +1093,7 @@ pmap_allocpte(pmap_t pmap, vm_offset_t va, int flags)
/*
* Calculate pagetable page index
*/
- ptepindex = va >> SEGSHIFT;
+ ptepindex = pmap_segshift(va);
retry:
/*
* Get the page directory entry
@@ -1205,7 +1216,7 @@ pmap_growkernel(vm_offset_t addr)
nkpt++;
pte = (pt_entry_t *)pageva;
- segtab_pde(kernel_segmap, kernel_vm_end) = (pd_entry_t)pte;
+ segtab_pde(kernel_segmap, kernel_vm_end) = pte;
/*
* The R[4-7]?00 stores only one copy of the Global bit in
@@ -1529,8 +1540,8 @@ pmap_remove(struct pmap *pmap, vm_offset_t sva, vm_offset_t eva)
goto out;
}
for (va = sva; va < eva; va = nva) {
- if (!*pmap_pde(pmap, va)) {
- nva = mips_segtrunc(va + MIPS_SEGSIZE);
+ if (pmap_segmap(pmap, va) == NULL) {
+ nva = mips_segtrunc(va + NBSEG);
continue;
}
pmap_remove_page(pmap, va);
@@ -1646,8 +1657,8 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
/*
* If segment table entry is empty, skip this segment.
*/
- if (!*pmap_pde(pmap, sva)) {
- sva = mips_segtrunc(sva + MIPS_SEGSIZE);
+ if (pmap_segmap(pmap, sva) == NULL) {
+ sva = mips_segtrunc(sva + NBSEG);
continue;
}
/*
@@ -1934,7 +1945,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Calculate pagetable page index
*/
- ptepindex = va >> SEGSHIFT;
+ ptepindex = pmap_segshift(va);
if (mpte && (mpte->pindex == ptepindex)) {
mpte->wire_count++;
} else {
@@ -2619,7 +2630,7 @@ pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
rv = FALSE;
PMAP_LOCK(pmap);
- if (*pmap_pde(pmap, addr)) {
+ if (pmap_segmap(pmap, addr) != NULL) {
pte = pmap_pte(pmap, addr);
rv = (*pte == 0);
}
OpenPOWER on IntegriCloud