diff options
author | Jake Burkholder <jake@FreeBSD.org> | 2001-10-20 16:17:04 +0000 |
---|---|---|
committer | Jake Burkholder <jake@FreeBSD.org> | 2001-10-20 16:17:04 +0000 |
commit | 6ef2d9a02df8e4b33853fa0d326ae28552b2b4e4 (patch) | |
tree | c55dc007e890858684e1c882664952fca43c3ea2 /sys/sparc64 | |
parent | d37e05e1c47f3a7b8953f139f19ade8941ae9995 (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.h | 4 | ||||
-rw-r--r-- | sys/sparc64/include/tsb.h | 18 | ||||
-rw-r--r-- | sys/sparc64/include/vmparam.h | 46 | ||||
-rw-r--r-- | sys/sparc64/sparc64/pmap.c | 144 |
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 |