pmap.c revision 81384
1/*-
2 * Copyright (c) 2001 Jake Burkholder.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/sparc64/sparc64/pmap.c 81384 2001-08-10 04:37:03Z jake $
27 */
28
29/*
30 * Manages physical address maps.
31 *
32 * In addition to hardware address maps, this module is called upon to
33 * provide software-use-only maps which may or may not be stored in the
34 * same form as hardware maps.  These pseudo-maps are used to store
35 * intermediate results from copy operations to and from address spaces.
36 *
37 * Since the information managed by this module is also stored by the
38 * logical address mapping module, this module may throw away valid virtual
39 * to physical mappings at almost any time.  However, invalidations of
40 * mappings must be done as requested.
41 *
42 * In order to cope with hardware architectures which make virtual to
43 * physical map invalidates expensive, this module may delay invalidate
44 * reduced protection operations until such time as they are actually
45 * necessary.  This module is given full information as to which processors
46 * are currently using which maps, and to when physical maps must be made
47 * correct.
48 */
49
50#include <sys/param.h>
51#include <sys/lock.h>
52#include <sys/mutex.h>
53#include <sys/proc.h>
54#include <sys/systm.h>
55#include <sys/vmmeter.h>
56
57#include <dev/ofw/openfirm.h>
58
59#include <vm/vm.h>
60#include <vm/vm_param.h>
61#include <vm/vm_kern.h>
62#include <vm/vm_page.h>
63#include <vm/vm_map.h>
64#include <vm/vm_object.h>
65#include <vm/vm_extern.h>
66#include <vm/vm_pageout.h>
67#include <vm/vm_pager.h>
68#include <vm/vm_zone.h>
69
70#include <machine/frame.h>
71#include <machine/pv.h>
72#include <machine/tlb.h>
73#include <machine/tte.h>
74#include <machine/tsb.h>
75
76#define	PMAP_DEBUG
77
78#define	PMAP_LOCK(pm)
79#define	PMAP_UNLOCK(pm)
80
81#define	dcache_global_flush(pa)
82#define	icache_global_flush(pa)
83
84struct mem_region {
85	vm_offset_t mr_start;
86	vm_offset_t mr_size;
87};
88
89struct ofw_map {
90	vm_offset_t om_start;
91	vm_offset_t om_size;
92	u_long	om_tte;
93};
94
95/*
96 * Virtual address of message buffer.
97 */
98struct msgbuf *msgbufp;
99
100/*
101 * Physical addresses of first and last available physical page.
102 */
103vm_offset_t avail_start;
104vm_offset_t avail_end;
105
106/*
107 * Map of physical memory reagions.
108 */
109vm_offset_t phys_avail[10];
110
111/*
112 * First and last available kernel virtual addresses.
113 */
114vm_offset_t virtual_avail;
115vm_offset_t virtual_end;
116vm_offset_t kernel_vm_end;
117
118/*
119 * Kernel pmap handle and associated storage.
120 */
121pmap_t kernel_pmap;
122static struct pmap kernel_pmap_store;
123
124/*
125 * Map of free and in use hardware contexts and index of first potentially
126 * free context.
127 */
128static char pmap_context_map[PMAP_CONTEXT_MAX];
129static u_int pmap_context_base;
130
131/*
132 * Virtual addresses of free space for temporary mappings.  Used for copying
133 * and zeroing physical pages.
134 */
135static vm_offset_t CADDR1;
136static vm_offset_t CADDR2;
137
138/*
139 * Allocate and free hardware context numbers.
140 */
141static u_int pmap_context_alloc(void);
142static void pmap_context_destroy(u_int i);
143
144/*
145 * Allocate physical memory for use in pmap_bootstrap.
146 */
147static vm_offset_t pmap_bootstrap_alloc(vm_size_t size);
148
149/*
150 * Quick sort callout for comparing memory regions.
151 */
152static int mr_cmp(const void *a, const void *b);
153static int
154mr_cmp(const void *a, const void *b)
155{
156	return ((const struct mem_region *)a)->mr_start -
157	    ((const struct mem_region *)b)->mr_start;
158}
159
160/*
161 * Bootstrap the system enough to run with virtual memory.
162 */
163void
164pmap_bootstrap(vm_offset_t skpa, vm_offset_t ekva)
165{
166	struct mem_region mra[8];
167	ihandle_t pmem;
168	struct pmap *pm;
169	vm_offset_t pa;
170	vm_offset_t va;
171	struct tte tte;
172	int sz;
173	int i;
174	int j;
175
176	/*
177	 * Find out what physical memory is available from the prom and
178	 * initialize the phys_avail array.
179	 */
180	if ((pmem = OF_finddevice("/memory")) == -1)
181		panic("pmap_bootstrap: finddevice /memory");
182	if ((sz = OF_getproplen(pmem, "available")) == -1)
183		panic("pmap_bootstrap: getproplen /memory/available");
184	if (sizeof(phys_avail) < sz)
185		panic("pmap_bootstrap: phys_avail too small");
186	bzero(mra, sz);
187	if (OF_getprop(pmem, "available", mra, sz) == -1)
188		panic("pmap_bootstrap: getprop /memory/available");
189	sz /= sizeof(*mra);
190	qsort(mra, sz, sizeof *mra, mr_cmp);
191	for (i = 0, j = 0; i < sz; i++, j += 2) {
192		phys_avail[j] = mra[i].mr_start;
193		phys_avail[j + 1] = mra[i].mr_start + mra[i].mr_size;
194	}
195
196	/*
197	 * Initialize the kernel pmap (which is statically allocated).
198	 */
199	pm = &kernel_pmap_store;
200	pm->pm_context = TLB_CTX_KERNEL;
201	pm->pm_active = ~0;
202	pm->pm_count = 1;
203	kernel_pmap = pm;
204
205	/*
206	 * Allocate the kernel tsb and lock it in the tlb.
207	 */
208	pa = pmap_bootstrap_alloc(TSB_KERNEL_SIZE);
209	if (pa & PAGE_MASK_4M)
210		panic("pmap_bootstrap: tsb unaligned\n");
211	tsb_kernel_phys = pa;
212	for (i = 0; i < TSB_KERNEL_PAGES; i++) {
213		va = TSB_KERNEL_MIN_ADDRESS + i * PAGE_SIZE_4M;
214		tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va);
215		tte.tte_data = TD_V | TD_4M | TD_VA_LOW(va) | TD_PA(pa) |
216		    TD_MOD | TD_REF | TD_TSB | TD_L | TD_CP | TD_P | TD_W;
217		tlb_store_slot(TLB_DTLB, va, TLB_CTX_KERNEL, tte,
218		    TLB_SLOT_TSB_KERNEL_MIN + i);
219	}
220	bzero((void *)va, TSB_KERNEL_SIZE);
221	stxa(AA_IMMU_TSB, ASI_IMMU,
222	    (va >> (STTE_SHIFT - TTE_SHIFT)) | TSB_SIZE_REG);
223	stxa(AA_DMMU_TSB, ASI_DMMU,
224	    (va >> (STTE_SHIFT - TTE_SHIFT)) | TSB_SIZE_REG);
225	membar(Sync);
226
227	/*
228	 * Calculate the first and last available physical addresses.
229	 */
230	avail_start = phys_avail[0];
231	for (i = 0; phys_avail[i + 2] != 0; i += 2)
232		;
233	avail_end = phys_avail[i + 1];
234
235	/*
236	 * Allocate physical memory for the heads of the stte alias chains.
237	 */
238	sz = round_page(((avail_end - avail_start) >> PAGE_SHIFT) *
239	    sizeof(struct pv_head));
240	pv_table = pmap_bootstrap_alloc(sz);
241	/* XXX */
242	avail_start += sz;
243	for (i = 0; i < sz; i += sizeof(struct pv_head))
244		pvh_set_first(pv_table + i, 0);
245
246	/*
247	 * Set the start and end of kva.  The kernel is loaded at the first
248	 * available 4 meg super page, so round up to the end of the page.
249	 */
250	virtual_avail = roundup(ekva, PAGE_SIZE_4M);
251	virtual_end = VM_MAX_KERNEL_ADDRESS;
252
253	/*
254	 * Allocate virtual address space for copying and zeroing pages of
255	 * physical memory.
256	 */
257	CADDR1 = virtual_avail;
258	virtual_avail += PAGE_SIZE;
259	CADDR2 = virtual_avail;
260	virtual_avail += PAGE_SIZE;
261
262	/*
263	 * Set the secondary context to be the kernel context (needed for
264	 * fp block operations in the kernel).
265	 */
266	stxa(AA_DMMU_SCXR, ASI_DMMU, TLB_CTX_KERNEL);
267	membar(Sync);
268}
269
270/*
271 * Allocate a physical page of memory directly from the phys_avail map.
272 * Can only be called from pmap_bootstrap before avail start and end are
273 * calculated.
274 */
275static vm_offset_t
276pmap_bootstrap_alloc(vm_size_t size)
277{
278	vm_offset_t pa;
279	int i;
280
281	size = round_page(size);
282	for (i = 0; phys_avail[i + 1] != 0; i += 2) {
283		if (phys_avail[i + 1] - phys_avail[i] < size)
284			continue;
285		pa = phys_avail[i];
286		phys_avail[i] += size;
287		return (pa);
288	}
289	panic("pmap_bootstrap_alloc");
290}
291
292/*
293 * Allocate a hardware context number from the context map.
294 */
295static u_int
296pmap_context_alloc(void)
297{
298	u_int i;
299
300	i = pmap_context_base;
301	do {
302		if (pmap_context_map[i] == 0) {
303			pmap_context_map[i] = 1;
304			pmap_context_base = (i + 1) & (PMAP_CONTEXT_MAX - 1);
305			return (i);
306		}
307	} while ((i = (i + 1) & (PMAP_CONTEXT_MAX - 1)) != pmap_context_base);
308	panic("pmap_context_alloc");
309}
310
311/*
312 * Free a hardware context number back to the context map.
313 */
314static void
315pmap_context_destroy(u_int i)
316{
317
318	pmap_context_map[i] = 0;
319}
320
321/*
322 * Map a range of physical addresses into kernel virtual address space.
323 *
324 * The value passed in *virt is a suggested virtual address for the mapping.
325 * Architectures which can support a direct-mapped physical to virtual region
326 * can return the appropriate address within that region, leaving '*virt'
327 * unchanged.  We cannot and therefore do not; *virt is updated with the
328 * first usable address after the mapped region.
329 */
330vm_offset_t
331pmap_map(vm_offset_t *virt, vm_offset_t pa_start, vm_offset_t pa_end, int prot)
332{
333	vm_offset_t sva;
334	vm_offset_t va;
335
336	sva = *virt;
337	va = sva;
338	for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE)
339		pmap_kenter(va, pa_start);
340	*virt = va;
341	return (sva);
342}
343
344/*
345 * Map a wired page into kernel virtual address space.
346 */
347void
348pmap_kenter(vm_offset_t va, vm_offset_t pa)
349{
350	struct stte *stp;
351	struct tte tte;
352
353	tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va);
354	tte.tte_data = TD_V | TD_8K | TD_VA_LOW(va) | TD_PA(pa) |
355	    TD_MOD | TD_REF | TD_CP | TD_P | TD_W;
356	stp = tsb_kvtostte(va);
357	stp->st_tte = tte;
358}
359
360/*
361 * Remove a wired page from kernel virtual address space.
362 */
363void
364pmap_kremove(vm_offset_t va)
365{
366	struct stte *stp;
367
368	stp = tsb_kvtostte(va);
369	tte_invalidate(&stp->st_tte);
370}
371
372/*
373 * Map a list of wired pages into kernel virtual address space.  This is
374 * intended for temporary mappings which do not need page modification or
375 * references recorded.  Existing mappings in the region are overwritten.
376 */
377void
378pmap_qenter(vm_offset_t va, vm_page_t *m, int count)
379{
380	int i;
381
382	for (i = 0; i < count; i++, va += PAGE_SIZE)
383		pmap_kenter(va, VM_PAGE_TO_PHYS(m[i]));
384}
385
386/*
387 * Remove page mappings from kernel virtual address space.  Intended for
388 * temporary mappings entered by pmap_qenter.
389 */
390void
391pmap_qremove(vm_offset_t va, int count)
392{
393	int i;
394
395	for (i = 0; i < count; i++, va += PAGE_SIZE)
396		pmap_kremove(va);
397}
398
399/*
400 * Map the given physical page at the specified virtual address in the
401 * target pmap with the protection requested.  If specified the page
402 * will be wired down.
403 */
404void
405pmap_enter(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
406	   boolean_t wired)
407{
408	struct stte *stp;
409	struct tte tte;
410	vm_offset_t pa;
411
412	pa = VM_PAGE_TO_PHYS(m);
413	tte.tte_tag = TT_CTX(pm->pm_context) | TT_VA(va);
414	tte.tte_data = TD_V | TD_8K | TD_VA_LOW(va) | TD_PA(pa) |
415	    TD_CP | TD_CV;
416	if (pm->pm_context == TLB_CTX_KERNEL)
417		tte.tte_data |= TD_P;
418	if (wired == TRUE) {
419		tte.tte_data |= TD_REF;
420		if (prot & VM_PROT_WRITE)
421			tte.tte_data |= TD_MOD;
422	}
423	if (prot & VM_PROT_WRITE)
424		tte.tte_data |= TD_W;
425	if (prot & VM_PROT_EXECUTE) {
426		tte.tte_data |= TD_EXEC;
427		icache_global_flush(pa);
428	}
429	if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
430		tte.tte_data |= TD_MNG;
431
432	PMAP_LOCK(pm);
433	if ((stp = tsb_stte_lookup(pm, va)) != NULL) {
434		if (stp->st_tte.tte_data & TD_MNG)
435			pv_remove_virt(stp);
436		tsb_stte_remove(stp);
437		if (tte.tte_data & TD_MNG)
438			pv_insert(pm, pa, va, stp);
439		stp->st_tte = tte;
440	} else {
441		tsb_tte_enter(pm, va, tte);
442	}
443	PMAP_UNLOCK(pm);
444}
445
446void
447pmap_remove(pmap_t pm, vm_offset_t start, vm_offset_t end)
448{
449	struct stte *stp;
450
451	PMAP_LOCK(pm);
452	for (; start < end; start += PAGE_SIZE) {
453		if ((stp = tsb_stte_lookup(pm, start)) == NULL)
454			continue;
455		if (stp->st_tte.tte_data & TD_MNG)
456			pv_remove_virt(stp);
457		tsb_stte_remove(stp);
458	}
459	PMAP_UNLOCK(pm);
460}
461
462/*
463 * Initialize the pmap module.
464 */
465void
466pmap_init(vm_offset_t phys_start, vm_offset_t phys_end)
467{
468}
469
470void
471pmap_init2(void)
472{
473}
474
475/*
476 * Initialize the pmap associated with process 0.
477 */
478void
479pmap_pinit0(pmap_t pm)
480{
481
482	pm = &kernel_pmap_store;
483	pm->pm_context = pmap_context_alloc();
484	pm->pm_active = 0;
485	pm->pm_count = 1;
486	bzero(&pm->pm_stats, sizeof(pm->pm_stats));
487}
488
489/*
490 * Initialize a preallocated and zeroed pmap structure.
491 */
492void
493pmap_pinit(pmap_t pm)
494{
495	struct stte *stp;
496
497	pm->pm_object = vm_object_allocate(OBJT_DEFAULT, 16);
498	pm->pm_context = pmap_context_alloc();
499	pm->pm_active = 0;
500	pm->pm_count = 1;
501	stp = &pm->pm_stte;
502	stp->st_tte = tsb_page_alloc(pm, (vm_offset_t)tsb_base(0));
503	bzero(&pm->pm_stats, sizeof(pm->pm_stats));
504}
505
506void
507pmap_pinit2(pmap_t pmap)
508{
509}
510
511/*
512 * Grow the number of kernel page table entries.  Unneeded.
513 */
514void
515pmap_growkernel(vm_offset_t addr)
516{
517}
518
519/*
520 * Zero a page of physical memory by temporarily mapping it into the tlb.
521 */
522void
523pmap_zero_page(vm_offset_t pa)
524{
525	struct tte tte;
526	vm_offset_t va;
527
528	va = CADDR2;
529	tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va);
530	tte.tte_data = TD_V | TD_8K | TD_PA(pa) | TD_L | TD_CP | TD_P | TD_W;
531	tlb_store(TLB_DTLB, va, TLB_CTX_KERNEL, tte);
532	bzero((void *)va, PAGE_SIZE);
533	tlb_page_demap(TLB_DTLB, TLB_CTX_KERNEL, va);
534}
535
536/*
537 * Make the specified page pageable (or not).  Unneeded.
538 */
539void
540pmap_pageable(pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
541	      boolean_t pageable)
542{
543}
544
545/*
546 * Create the kernel stack and user structure for a new process.  This
547 * routine directly affects the performance of fork().
548 */
549void
550pmap_new_proc(struct proc *p)
551{
552	struct user *u;
553	vm_object_t o;
554	vm_page_t m;
555	u_int i;
556
557	if ((o = p->p_upages_obj) == NULL) {
558		o = vm_object_allocate(OBJT_DEFAULT, UPAGES);
559		p->p_upages_obj = o;
560	}
561	if ((u = p->p_addr) == NULL) {
562		u = (struct user *)kmem_alloc_nofault(kernel_map,
563		    UPAGES * PAGE_SIZE);
564		KASSERT(u != NULL, ("pmap_new_proc: u area\n"));
565		p->p_addr = u;
566	}
567	for (i = 0; i < UPAGES; i++) {
568		m = vm_page_grab(o, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
569		m->wire_count++;
570		cnt.v_wire_count++;
571
572		pmap_kenter((vm_offset_t)u + i * PAGE_SIZE,
573		    VM_PAGE_TO_PHYS(m));
574
575		vm_page_wakeup(m);
576		vm_page_flag_clear(m, PG_ZERO);
577		vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
578		m->valid = VM_PAGE_BITS_ALL;
579	}
580}
581
582void
583pmap_page_protect(vm_page_t m, vm_prot_t prot)
584{
585
586	if (m->flags & PG_FICTITIOUS || prot & VM_PROT_WRITE)
587		return;
588	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE))
589		pv_bit_clear(m, TD_W);
590	else
591		pv_global_remove_all(m);
592}
593
594void
595pmap_clear_modify(vm_page_t m)
596{
597
598	if (m->flags & PG_FICTITIOUS)
599		return;
600	pv_bit_clear(m, TD_MOD);
601}
602
603void
604pmap_activate(struct proc *p)
605{
606	TODO;
607}
608
609vm_offset_t
610pmap_addr_hint(vm_object_t object, vm_offset_t va, vm_size_t size)
611{
612	TODO;
613	return (0);
614}
615
616void
617pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
618{
619	TODO;
620}
621
622void
623pmap_collect(void)
624{
625	TODO;
626}
627
628void
629pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
630	  vm_size_t len, vm_offset_t src_addr)
631{
632	TODO;
633}
634
635void
636pmap_copy_page(vm_offset_t src, vm_offset_t dst)
637{
638	TODO;
639}
640
641void
642pmap_zero_page_area(vm_offset_t pa, int off, int size)
643{
644	struct tte tte;
645	vm_offset_t va;
646
647	KASSERT(off + size <= PAGE_SIZE, ("pmap_zero_page_area: bad off/size"));
648	va = CADDR2;
649	tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va);
650	tte.tte_data = TD_V | TD_8K | TD_PA(pa) | TD_L | TD_CP | TD_P | TD_W;
651	tlb_store(TLB_DTLB, va, TLB_CTX_KERNEL, tte);
652	bzero((char *)va + off, size);
653	tlb_page_demap(TLB_DTLB, TLB_CTX_KERNEL, va);
654}
655
656vm_offset_t
657pmap_extract(pmap_t pmap, vm_offset_t va)
658{
659	TODO;
660	return (0);
661}
662
663boolean_t
664pmap_is_modified(vm_page_t m)
665{
666	TODO;
667	return (0);
668}
669
670void
671pmap_clear_reference(vm_page_t m)
672{
673	TODO;
674}
675
676int
677pmap_ts_referenced(vm_page_t m)
678{
679	TODO;
680	return (0);
681}
682
683vm_offset_t
684pmap_kextract(vm_offset_t va)
685{
686	TODO;
687	return (0);
688}
689
690int
691pmap_mincore(pmap_t pmap, vm_offset_t addr)
692{
693	TODO;
694	return (0);
695}
696
697void
698pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
699		    vm_pindex_t pindex, vm_size_t size, int limit)
700{
701	/* XXX */
702}
703
704boolean_t
705pmap_page_exists(pmap_t pmap, vm_page_t m)
706{
707	TODO;
708	return (0);
709}
710
711void
712pmap_prefault(pmap_t pmap, vm_offset_t va, vm_map_entry_t entry)
713{
714	/* XXX */
715}
716
717void
718pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
719{
720	/* XXX */
721}
722
723vm_offset_t
724pmap_phys_address(int ppn)
725{
726	TODO;
727	return (0);
728}
729
730void
731pmap_reference(pmap_t pm)
732{
733	if (pm != NULL)
734		pm->pm_count++;
735}
736
737void
738pmap_release(pmap_t pmap)
739{
740	TODO;
741}
742
743void
744pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
745{
746
747	/* XXX */
748}
749
750void
751pmap_swapin_proc(struct proc *p)
752{
753	TODO;
754}
755
756void
757pmap_swapout_proc(struct proc *p)
758{
759	TODO;
760}
761