aboutsummaryrefslogtreecommitdiff
path: root/sys/sparc64
diff options
context:
space:
mode:
authorJake Burkholder <jake@FreeBSD.org>2001-10-20 16:17:04 +0000
committerJake Burkholder <jake@FreeBSD.org>2001-10-20 16:17:04 +0000
commit6ef2d9a02df8e4b33853fa0d326ae28552b2b4e4 (patch)
treec55dc007e890858684e1c882664952fca43c3ea2 /sys/sparc64
parentd37e05e1c47f3a7b8953f139f19ade8941ae9995 (diff)
Parameterize the size of the kernel virtual address space on KVA_PAGES.
Don't use a hard coded address constant for the virtual address of the kernel tsb. Allocate kernel virtual address space for the kernel tsb at runtime. Remove unused parameter to pmap_bootstrap. Adapt pmap.c to use KVA_PAGES. Map the message buffer too. Add some traces. Implement pmap_protect.
Notes
Notes: svn path=/head/; revision=85241
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/include/pmap.h4
-rw-r--r--sys/sparc64/include/tsb.h18
-rw-r--r--sys/sparc64/include/vmparam.h46
-rw-r--r--sys/sparc64/sparc64/pmap.c144
4 files changed, 163 insertions, 49 deletions
diff --git a/sys/sparc64/include/pmap.h b/sys/sparc64/include/pmap.h
index 90cf94f3dcde..33fa7588992a 100644
--- a/sys/sparc64/include/pmap.h
+++ b/sys/sparc64/include/pmap.h
@@ -64,7 +64,7 @@ struct pmap {
struct pmap_statistics pm_stats;
};
-void pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva);
+void pmap_bootstrap(vm_offset_t ekva);
vm_offset_t pmap_kextract(vm_offset_t va);
void pmap_kenter_flags(vm_offset_t va, vm_offset_t pa, u_long flags);
@@ -77,6 +77,8 @@ extern vm_offset_t phys_avail[];
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;
+extern vm_offset_t msgbuf_phys;
+
static __inline int
pmap_track_modified(vm_offset_t va)
{
diff --git a/sys/sparc64/include/tsb.h b/sys/sparc64/include/tsb.h
index ec1b1d1c202c..32e8a9884870 100644
--- a/sys/sparc64/include/tsb.h
+++ b/sys/sparc64/include/tsb.h
@@ -32,8 +32,7 @@
#ifndef _MACHINE_TSB_H_
#define _MACHINE_TSB_H_
-#define TSB_KERNEL_MIN_ADDRESS (0xa0000000)
-#define TSB_USER_MIN_ADDRESS (0xb0000000)
+#define TSB_USER_MIN_ADDRESS (UPT_MIN_ADDRESS)
#define TSB_MASK_WIDTH (6)
@@ -59,10 +58,11 @@
#define TSB_DEPTH (7)
-#define TSB_KERNEL_PAGES (1)
-#define TSB_KERNEL_SIZE (TSB_KERNEL_PAGES * PAGE_SIZE_4M)
-#define TSB_KERNEL_MASK ((TSB_KERNEL_SIZE >> STTE_SHIFT) - 1)
+#define TSB_KERNEL_MASK \
+ (((KVA_PAGES * PAGE_SIZE_4M) >> STTE_SHIFT) - 1)
+#define TSB_KERNEL_VA_MASK (TSB_KERNEL_MASK << STTE_SHIFT)
+extern struct stte *tsb_kernel;
extern vm_offset_t tsb_kernel_phys;
static __inline struct stte *
@@ -128,7 +128,7 @@ tsb_stte_vtophys(pmap_t pm, struct stte *stp)
va = (vm_offset_t)stp;
if (pm == kernel_pmap)
- return (tsb_kernel_phys + (va - TSB_KERNEL_MIN_ADDRESS));
+ return (tsb_kernel_phys + (va - (vm_offset_t)tsb_kernel));
if (trunc_page(va) == TSB_USER_MIN_ADDRESS)
data = pm->pm_stte.st_tte.tte_data;
@@ -154,11 +154,7 @@ tsb_vtobucket(vm_offset_t va, u_int level)
static __inline struct stte *
tsb_kvpntostte(vm_offset_t vpn)
{
- struct stte *stp;
-
- stp = (struct stte *)(TSB_KERNEL_MIN_ADDRESS +
- ((vpn & TSB_KERNEL_MASK) << STTE_SHIFT));
- return (stp);
+ return (&tsb_kernel[vpn & TSB_KERNEL_MASK]);
}
static __inline struct stte *
diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h
index 2b3c2449e732..fd2bae466a7d 100644
--- a/sys/sparc64/include/vmparam.h
+++ b/sys/sparc64/include/vmparam.h
@@ -90,10 +90,50 @@
#define VM_KMEM_SIZE (12*1024*1024)
#endif
-#define VM_MIN_KERNEL_ADDRESS (0xc0000000)
-#define VM_MAX_KERNEL_ADDRESS (0xffffe000)
+/*
+ * Number of 4 meg pages to use for the kernel tsb.
+ */
+#ifndef KVA_PAGES
+#define KVA_PAGES (1)
+#endif
+
+/*
+ * Range of kernel virtual addresses. max = min + range.
+ */
+#define KVA_RANGE \
+ ((KVA_PAGES * PAGE_SIZE_4M) << (PAGE_SHIFT - STTE_SHIFT))
+
+/*
+ * Lowest kernel virtual address, where the kernel is loaded.
+ *
+ * If we are using less than 4 super pages for the kernel tsb, the address
+ * space is less than 4 gigabytes, so put it at the end of the first 4
+ * gigbytes. This allows the kernel and the firmware mappings to be mapped
+ * with a single contiguous tsb. Otherwise start at 0, we'll cover them
+ * anyway.
+ *
+ * ie:
+ * kva_pages = 1
+ * vm_max_kernel_address 0xffffe000
+ * openfirmware 0xf0000000
+ * kernbase 0xc0000000
+ * kva_pages = 8
+ * vm_max_kernel_address 0x1ffffe000
+ * openfirmware 0xf0000000
+ * kernbase 0x0
+ *
+ * There are at least 4 pages of dynamic linker junk before kernel text begins,
+ * so starting at zero is fairly safe.
+ */
+#if KVA_PAGES < 4
+#define VM_MIN_KERNEL_ADDRESS ((1UL << 32) - KVA_RANGE)
+#else
+#define VM_MIN_KERNEL_ADDRESS (0)
+#endif
-#define KERNBASE (0xc0000000)
+#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + KVA_RANGE - PAGE_SIZE)
+#define UPT_MIN_ADDRESS (VM_MIN_KERNEL_ADDRESS + KVA_RANGE)
+#define KERNBASE (VM_MIN_KERNEL_ADDRESS)
/*
* Initial pagein size of beginning of executable file.
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index 5db7d2f7560e..4abbd45f7c21 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -63,8 +63,11 @@
* correct.
*/
+#include "opt_msgbuf.h"
+
#include <sys/param.h>
#include <sys/lock.h>
+#include <sys/msgbuf.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/systm.h>
@@ -109,9 +112,10 @@ struct ofw_map {
};
/*
- * Virtual address of message buffer.
+ * Virtual and physical address of message buffer.
*/
struct msgbuf *msgbufp;
+vm_offset_t msgbuf_phys;
/*
* Physical addresses of first and last available physical page.
@@ -179,7 +183,7 @@ mr_cmp(const void *a, const void *b)
* Bootstrap the system enough to run with virtual memory.
*/
void
-pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva)
+pmap_bootstrap(vm_offset_t ekva)
{
struct pmap *pm;
struct stte *stp;
@@ -194,8 +198,16 @@ pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva)
int j;
/*
+ * Set the start and end of kva. The kernel is loaded at the first
+ * available 4 meg super page, so round up to the end of the page.
+ */
+ virtual_avail = roundup2(ekva, PAGE_SIZE_4M);
+ virtual_end = VM_MAX_KERNEL_ADDRESS;
+
+ /*
* Find out what physical memory is available from the prom and
- * initialize the phys_avail array.
+ * initialize the phys_avail array. This must be done before
+ * pmap_bootstrap_alloc is called.
*/
if ((pmem = OF_finddevice("/memory")) == -1)
panic("pmap_bootstrap: finddevice /memory");
@@ -219,30 +231,38 @@ pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva)
}
/*
- * Initialize the kernel pmap (which is statically allocated).
- */
- pm = &kernel_pmap_store;
- pm->pm_context = TLB_CTX_KERNEL;
- pm->pm_active = ~0;
- pm->pm_count = 1;
- kernel_pmap = pm;
-
- /*
* Allocate the kernel tsb and lock it in the tlb.
*/
- pa = pmap_bootstrap_alloc(TSB_KERNEL_SIZE);
+ pa = pmap_bootstrap_alloc(KVA_PAGES * PAGE_SIZE_4M);
if (pa & PAGE_MASK_4M)
panic("pmap_bootstrap: tsb unaligned\n");
tsb_kernel_phys = pa;
- for (i = 0; i < TSB_KERNEL_PAGES; i++) {
- va = TSB_KERNEL_MIN_ADDRESS + i * PAGE_SIZE_4M;
+ tsb_kernel = (struct stte *)virtual_avail;
+ virtual_avail += KVA_PAGES * PAGE_SIZE_4M;
+ for (i = 0; i < KVA_PAGES; i++) {
+ va = (vm_offset_t)tsb_kernel + i * PAGE_SIZE_4M;
tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va);
tte.tte_data = TD_V | TD_4M | TD_VA_LOW(va) | TD_PA(pa) |
TD_L | TD_CP | TD_P | TD_W;
tlb_store_slot(TLB_DTLB, va, TLB_CTX_KERNEL, tte,
TLB_SLOT_TSB_KERNEL_MIN + i);
}
- bzero((void *)va, TSB_KERNEL_SIZE);
+ bzero(tsb_kernel, KVA_PAGES * PAGE_SIZE_4M);
+
+ /*
+ * Load the tsb registers.
+ */
+ stxa(AA_DMMU_TSB, ASI_DMMU,
+ (vm_offset_t)tsb_kernel >> (STTE_SHIFT - TTE_SHIFT));
+ stxa(AA_IMMU_TSB, ASI_IMMU,
+ (vm_offset_t)tsb_kernel >> (STTE_SHIFT - TTE_SHIFT));
+ membar(Sync);
+ flush(va);
+
+ /*
+ * Allocate the message buffer.
+ */
+ msgbuf_phys = pmap_bootstrap_alloc(MSGBUF_SIZE);
/*
* Add the prom mappings to the kernel tsb.
@@ -286,6 +306,21 @@ pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva)
avail_end = phys_avail[i + 1];
/*
+ * Allocate virtual address space for copying and zeroing pages of
+ * physical memory.
+ */
+ CADDR1 = virtual_avail;
+ virtual_avail += PAGE_SIZE;
+ CADDR2 = virtual_avail;
+ virtual_avail += PAGE_SIZE;
+
+ /*
+ * Allocate virtual address space for the message buffer.
+ */
+ msgbufp = (struct msgbuf *)virtual_avail;
+ virtual_avail += round_page(MSGBUF_SIZE);
+
+ /*
* Allocate physical memory for the heads of the stte alias chains.
*/
sz = round_page(((avail_end - avail_start) >> PAGE_SHIFT) *
@@ -297,20 +332,13 @@ pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva)
pvh_set_first(pv_table + i, 0);
/*
- * Set the start and end of kva. The kernel is loaded at the first
- * available 4 meg super page, so round up to the end of the page.
- */
- virtual_avail = roundup(ekva, PAGE_SIZE_4M);
- virtual_end = VM_MAX_KERNEL_ADDRESS;
-
- /*
- * Allocate virtual address space for copying and zeroing pages of
- * physical memory.
+ * Initialize the kernel pmap (which is statically allocated).
*/
- CADDR1 = virtual_avail;
- virtual_avail += PAGE_SIZE;
- CADDR2 = virtual_avail;
- virtual_avail += PAGE_SIZE;
+ pm = &kernel_pmap_store;
+ pm->pm_context = TLB_CTX_KERNEL;
+ pm->pm_active = ~0;
+ pm->pm_count = 1;
+ kernel_pmap = pm;
/*
* Set the secondary context to be the kernel context (needed for
@@ -454,8 +482,9 @@ pmap_kremove(vm_offset_t va)
struct stte *stp;
stp = tsb_kvtostte(va);
- CTR2(KTR_PMAP, "pmap_kremove: va=%#lx stp=%p", va, stp);
- tte_invalidate(&stp->st_tte);
+ CTR3(KTR_PMAP, "pmap_kremove: va=%#lx stp=%p data=%#lx", va, stp,
+ stp->st_tte.tte_data);
+ tsb_stte_remove(stp);
}
/*
@@ -550,6 +579,8 @@ pmap_remove(pmap_t pm, vm_offset_t start, vm_offset_t end)
{
struct stte *stp;
+ CTR3(KTR_PMAP, "pmap_remove: pm=%p start=%#lx end=%#lx",
+ pm, start, end);
KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap,
("pmap_remove: non current pmap"));
PMAP_LOCK(pm);
@@ -934,13 +965,12 @@ pmap_addr_hint(vm_object_t object, vm_offset_t va, vm_size_t size)
void
pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
{
- TODO;
+ /* XXX */
}
void
pmap_collect(void)
{
- TODO;
}
void
@@ -958,6 +988,8 @@ pmap_copy_page(vm_offset_t src, vm_offset_t dst)
{
struct tte tte;
+ CTR2(KTR_PMAP, "pmap_copy_page: src=%#lx dst=%#lx", src, dst);
+
tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(CADDR1);
tte.tte_data = TD_V | TD_8K | TD_PA(src) | TD_L | TD_CP | TD_P | TD_W;
tlb_store(TLB_DTLB, CADDR1, TLB_CTX_KERNEL, tte);
@@ -980,6 +1012,8 @@ pmap_zero_page(vm_offset_t pa)
{
struct tte tte;
+ CTR1(KTR_PMAP, "pmap_zero_page: pa=%#lx", pa);
+
tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(CADDR2);
tte.tte_data = TD_V | TD_8K | TD_PA(pa) | TD_L | TD_CP | TD_P | TD_W;
tlb_store(TLB_DTLB, CADDR2, TLB_CTX_KERNEL, tte);
@@ -992,6 +1026,9 @@ pmap_zero_page_area(vm_offset_t pa, int off, int size)
{
struct tte tte;
+ CTR3(KTR_PMAP, "pmap_zero_page_area: pa=%#lx off=%#x size=%#x",
+ pa, off, size);
+
KASSERT(off + size <= PAGE_SIZE, ("pmap_zero_page_area: bad off/size"));
tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(CADDR2);
tte.tte_data = TD_V | TD_8K | TD_PA(pa) | TD_L | TD_CP | TD_P | TD_W;
@@ -1072,9 +1109,48 @@ pmap_prefault(pmap_t pm, vm_offset_t va, vm_map_entry_t entry)
void
pmap_protect(pmap_t pm, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
{
+ struct stte *stp;
+ vm_page_t m;
+ u_long data;
+
KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap,
("pmap_protect: non current pmap"));
- /* XXX */
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pm, sva, eva);
+ return;
+ }
+
+ if (prot & VM_PROT_WRITE)
+ return;
+
+ for (; sva < eva; sva += PAGE_SIZE) {
+ if ((stp = tsb_stte_lookup(pm, sva)) != NULL) {
+ data = stp->st_tte.tte_data;
+ if ((data & TD_MNG) != 0) {
+ m = NULL;
+ if ((data & TD_REF) != 0) {
+ m = PHYS_TO_VM_PAGE(TD_PA(data));
+ vm_page_flag_set(m, PG_REFERENCED);
+ data &= ~TD_REF;
+ }
+ if ((data & TD_W) != 0 &&
+ pmap_track_modified(sva)) {
+ if (m == NULL)
+ m = PHYS_TO_VM_PAGE(TD_PA(data));
+ vm_page_dirty(m);
+ data &= ~TD_W;
+ }
+ }
+
+ data &= ~TD_SW;
+
+ if (data != stp->st_tte.tte_data) {
+ stp->st_tte.tte_data = data;
+ tsb_tte_local_remove(&stp->st_tte);
+ }
+ }
+ }
}
vm_offset_t