Module Name: src
Committed By: reinoud
Date: Tue Dec 13 12:29:19 UTC 2011
Modified Files:
src/sys/arch/usermode/usermode: pmap.c
Log Message:
Implement a new TLB system. This fixes the TLB issues that has been plaguing
the pmap.
To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/sys/arch/usermode/usermode/pmap.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/usermode/usermode/pmap.c
diff -u src/sys/arch/usermode/usermode/pmap.c:1.75 src/sys/arch/usermode/usermode/pmap.c:1.76
--- src/sys/arch/usermode/usermode/pmap.c:1.75 Tue Dec 13 11:11:03 2011
+++ src/sys/arch/usermode/usermode/pmap.c Tue Dec 13 12:29:19 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.75 2011/12/13 11:11:03 reinoud Exp $ */
+/* $NetBSD: pmap.c,v 1.76 2011/12/13 12:29:19 reinoud Exp $ */
/*-
* Copyright (c) 2011 Reinoud Zandijk <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.75 2011/12/13 11:11:03 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.76 2011/12/13 12:29:19 reinoud Exp $");
#include "opt_memsize.h"
#include "opt_kmempages.h"
@@ -52,7 +52,6 @@ struct pv_entry {
uint8_t pv_vflags; /* per mapping flags */
#define PV_WIRED 0x01 /* wired mapping */
#define PV_UNMANAGED 0x02 /* entered by pmap_kenter_ */
-#define PV_MAPPEDIN 0x04 /* is actually mapped */
uint8_t pv_pflags; /* per phys page flags */
#define PV_REFERENCED 0x01
#define PV_MODIFIED 0x02
@@ -66,9 +65,10 @@ struct pmap {
struct pv_entry **pm_entries;
};
-static struct pv_entry *pv_table;
-static struct pmap pmap_kernel_store;
-struct pmap * const kernel_pmap_ptr = &pmap_kernel_store;
+static struct pv_entry *pv_table; /* physical pages */
+static struct pv_entry **tlb; /* current tlb mappings */
+static struct pmap pmap_kernel_store;
+struct pmap * const kernel_pmap_ptr = &pmap_kernel_store;
static pmap_t active_pmap = NULL;
@@ -117,7 +117,7 @@ pmap_bootstrap(void)
struct pmap *pmap;
paddr_t totmem_len;
paddr_t fpos, file_len;
- paddr_t pv_fpos, pm_fpos;
+ paddr_t pv_fpos, pm_fpos, tlb_fpos;
paddr_t wlen;
paddr_t user_len, barrier_len;
paddr_t pv_table_size;
@@ -307,6 +307,25 @@ pmap_bootstrap(void)
kmem_ext_cur_start += pm_entries_size;
fpos += pm_entries_size;
+ /* set up tlb space */
+ tlb = (struct pv_entry **) kmem_ext_cur_start;
+
+ tlb_fpos = fpos;
+ addr = thunk_mmap(tlb, pm_entries_size,
+ THUNK_PROT_READ | THUNK_PROT_WRITE,
+ THUNK_MAP_FILE | THUNK_MAP_FIXED | THUNK_MAP_SHARED,
+ mem_fh, tlb_fpos);
+ if (addr != (void *) tlb)
+ panic("pmap_bootstrap: can't map in tlb entries\n");
+
+ memset(tlb, 0, pm_entries_size); /* test and clear */
+
+ dprintf_debug("kernel tlb entries initialiased correctly\n");
+
+ /* advance */
+ kmem_ext_cur_start += pm_entries_size;
+ fpos += pm_entries_size;
+
/* kmem used [kmem_ext_start - kmem_ext_cur_start] */
kmem_ext_cur_end = kmem_ext_cur_start;
@@ -323,6 +342,12 @@ pmap_bootstrap(void)
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
}
dprintf_debug("kernel pmap entries mem added to the kernel pmap\n");
+ for (pg = 0; pg < pm_entries_size; pg += PAGE_SIZE) {
+ pa = tlb_fpos + pg;
+ va = (vaddr_t) tlb + pg;
+ pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
+ }
+ dprintf_debug("kernel tlb entries mem added to the kernel pmap\n");
/* add file space to uvm's FREELIST */
/* XXX really from 0? or from fpos to have better stats */
@@ -519,8 +544,8 @@ pmap_fault(pmap_t pmap, vaddr_t va, vm_p
return true;
}
- /* if its not mapped in, we have a TLB fault */
- if ((pv->pv_vflags & PV_MAPPEDIN) == 0) {
+ /* check the TLB, if NULL we have a TLB fault */
+ if (tlb[pv->pv_lpn] == NULL) {
if (pv->pv_mmap_ppl != THUNK_PROT_NONE) {
dprintf_debug("%s: tlb fault page lpn %"PRIiPTR"\n",
__func__, pv->pv_lpn);
@@ -606,9 +631,9 @@ pmap_page_activate(struct pv_entry *pv)
panic("pmap_page_activate: mmap failed (expected %p got %p): %d",
(void *)va, addr, thunk_geterrno());
- pv->pv_vflags &= ~PV_MAPPEDIN;
+ tlb[pv->pv_lpn] = NULL;
if (pv->pv_mmap_ppl != THUNK_PROT_NONE)
- pv->pv_vflags |= PV_MAPPEDIN;
+ tlb[pv->pv_lpn] = pv;
}
static void
@@ -625,7 +650,8 @@ pmap_page_deactivate(struct pv_entry *pv
(void *) va, (void *) pa, pv->pv_mmap_ppl, (void *) addr);
if (addr != (void *) va)
panic("pmap_page_deactivate: mmap failed");
- pv->pv_vflags &= ~PV_MAPPEDIN;
+
+ tlb[pv->pv_lpn] = NULL;
}
static void