pmap.c revision 1.126
1/*	$OpenBSD: pmap.c,v 1.126 2014/03/31 18:58:41 mpi Exp $ */
2
3/*
4 * Copyright (c) 2001, 2002, 2007 Dale Rahn.
5 * All rights reserved.
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Effort sponsored in part by the Defense Advanced Research Projects
29 * Agency (DARPA) and Air Force Research Laboratory, Air Force
30 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
31 */
32
33/*
34 * powerpc lazy icache managment.
35 * The icache does not snoop dcache accesses. The icache also will not load
36 * modified data from the dcache, but the unmodified data in ram.
37 * Before the icache is loaded, the dcache must be synced to ram to prevent
38 * the icache from loading stale data.
39 * pg->pg_flags PG_PMAP_EXE bit is used to track if the dcache is clean
40 * and the icache may have valid data in it.
41 * if the PG_PMAP_EXE bit is set (and the page is not currently RWX)
42 * the icache will only have valid code in it. If the bit is clear
43 * memory may not match the dcache contents or the icache may contain
44 * data from a previous page.
45 *
46 * pmap enter
47 * !E  NONE 	-> R	no action
48 * !E  NONE|R 	-> RW	no action
49 * !E  NONE|R 	-> RX	flush dcache, inval icache (that page only), set E
50 * !E  NONE|R 	-> RWX	flush dcache, inval icache (that page only), set E
51 * !E  NONE|RW 	-> RWX	flush dcache, inval icache (that page only), set E
52 *  E  NONE 	-> R	no action
53 *  E  NONE|R 	-> RW	clear PG_PMAP_EXE bit
54 *  E  NONE|R 	-> RX	no action
55 *  E  NONE|R 	-> RWX	no action
56 *  E  NONE|RW 	-> RWX	-invalid source state
57 *
58 * pamp_protect
59 *  E RW -> R	- invalid source state
60 * !E RW -> R	- no action
61 *  * RX -> R	- no action
62 *  * RWX -> R	- sync dcache, inval icache
63 *  * RWX -> RW	- clear PG_PMAP_EXE
64 *  * RWX -> RX	- sync dcache, inval icache
65 *  * * -> NONE	- no action
66 *
67 * pmap_page_protect (called with arg PROT_NONE if page is to be reused)
68 *  * RW -> R	- as pmap_protect
69 *  * RX -> R	- as pmap_protect
70 *  * RWX -> R	- as pmap_protect
71 *  * RWX -> RW	- as pmap_protect
72 *  * RWX -> RX	- as pmap_protect
73 *  * * -> NONE - clear PG_PMAP_EXE
74 *
75 */
76
77#include <sys/param.h>
78#include <sys/malloc.h>
79#include <sys/proc.h>
80#include <sys/queue.h>
81#include <sys/systm.h>
82#include <sys/pool.h>
83
84#include <uvm/uvm_extern.h>
85
86#include <machine/pcb.h>
87#include <machine/powerpc.h>
88#include <machine/pmap.h>
89
90#include <machine/db_machdep.h>
91#include <ddb/db_extern.h>
92#include <ddb/db_output.h>
93
94#include <powerpc/lock.h>
95
96struct pmap kernel_pmap_;
97static struct mem_region *pmap_mem, *pmap_avail;
98struct mem_region pmap_allocated[10];
99int pmap_cnt_avail;
100int pmap_cnt_allocated;
101
102struct pte_64  *pmap_ptable64;
103struct pte_32  *pmap_ptable32;
104int	pmap_ptab_cnt;
105u_int	pmap_ptab_mask;
106
107#define HTABSIZE_32	(pmap_ptab_cnt * 64)
108#define HTABMEMSZ_64	(pmap_ptab_cnt * 8 * sizeof(struct pte_64))
109#define HTABSIZE_64	(ffs(pmap_ptab_cnt) - 12)
110
111static u_int usedsr[NPMAPS / sizeof(u_int) / 8];
112paddr_t zero_page;
113paddr_t copy_src_page;
114paddr_t copy_dst_page;
115
116struct pte_desc {
117	/* Linked list of phys -> virt entries */
118	LIST_ENTRY(pte_desc) pted_pv_list;
119	union {
120		struct pte_32 pted_pte32;
121		struct pte_64 pted_pte64;
122	} p;
123	pmap_t pted_pmap;
124	vaddr_t pted_va;
125};
126
127void print_pteg(pmap_t pm, vaddr_t va);
128
129static inline void tlbsync(void);
130static inline void tlbie(vaddr_t ea);
131void tlbia(void);
132
133void pmap_attr_save(paddr_t pa, u_int32_t bits);
134void pmap_page_ro64(pmap_t pm, vaddr_t va, vm_prot_t prot);
135void pmap_page_ro32(pmap_t pm, vaddr_t va, vm_prot_t prot);
136
137/*
138 * LOCKING structures.
139 * This may not be correct, and doesn't do anything yet.
140 */
141#define pmap_simplelock_pm(pm)
142#define pmap_simpleunlock_pm(pm)
143#define pmap_simplelock_pv(pm)
144#define pmap_simpleunlock_pv(pm)
145
146/*
147 * Some functions are called in real mode and cannot be profiled.
148 */
149#define __noprof __attribute__((__no_instrument_function__))
150
151/* VP routines */
152int pmap_vp_enter(pmap_t pm, vaddr_t va, struct pte_desc *pted, int flags);
153struct pte_desc *pmap_vp_remove(pmap_t pm, vaddr_t va);
154void pmap_vp_destroy(pmap_t pm);
155struct pte_desc *pmap_vp_lookup(pmap_t pm, vaddr_t va) __noprof;
156
157/* PV routines */
158void pmap_enter_pv(struct pte_desc *pted, struct vm_page *);
159void pmap_remove_pv(struct pte_desc *pted);
160
161
162/* pte hash table routines */
163void pmap_hash_remove(struct pte_desc *);
164void pte_insert32(struct pte_desc *) __noprof;
165void pte_insert64(struct pte_desc *) __noprof;
166void pmap_fill_pte64(pmap_t, vaddr_t, paddr_t, struct pte_desc *, vm_prot_t,
167    int, int) __noprof;
168void pmap_fill_pte32(pmap_t, vaddr_t, paddr_t, struct pte_desc *, vm_prot_t,
169    int, int) __noprof;
170
171void pmap_syncicache_user_virt(pmap_t pm, vaddr_t va);
172
173void _pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, int flags,
174    int cache);
175void pmap_remove_pg(pmap_t pm, vaddr_t va);
176void pmap_kremove_pg(vaddr_t va);
177
178/* setup/initialization functions */
179void pmap_avail_setup(void);
180void pmap_avail_fixup(void);
181void pmap_remove_avail(paddr_t base, paddr_t end);
182void *pmap_steal_avail(size_t size, int align);
183
184/* asm interface */
185int pte_spill_r(u_int32_t, u_int32_t, u_int32_t, int) __noprof;
186
187u_int32_t pmap_setusr(pmap_t pm, vaddr_t va);
188void pmap_popusr(u_int32_t oldsr);
189
190/* pte invalidation */
191void pte_zap(void *ptp, struct pte_desc *pted);
192
193/* debugging */
194void pmap_print_pted(struct pte_desc *pted, int(*print)(const char *, ...));
195
196/* XXX - panic on pool get failures? */
197struct pool pmap_pmap_pool;
198struct pool pmap_vp_pool;
199struct pool pmap_pted_pool;
200
201int pmap_initialized = 0;
202int physmem;
203int physmaxaddr;
204
205void pmap_hash_lock_init(void);
206void pmap_hash_lock(int entry);
207void pmap_hash_unlock(int entry)  __noprof;
208int pmap_hash_lock_try(int entry) __noprof;
209
210volatile unsigned int pmap_hash_lock_word = 0;
211
212void
213pmap_hash_lock_init()
214{
215	pmap_hash_lock_word = 0;
216}
217
218int
219pmap_hash_lock_try(int entry)
220{
221	int val = 1 << entry;
222	int success, tmp;
223	__asm volatile (
224	    "1: lwarx	%0, 0, %3	\n"
225	    "	and.	%1, %2, %0	\n"
226	    "	li	%1, 0		\n"
227	    "	bne 2f			\n"
228	    "	or	%0, %2, %0	\n"
229	    "	stwcx.  %0, 0, %3	\n"
230	    "	li	%1, 1		\n"
231	    "	bne-	1b		\n"
232	    "2:				\n"
233	    : "=&r" (tmp), "=&r" (success)
234	    : "r" (val), "r" (&pmap_hash_lock_word)
235	    : "memory");
236	return success;
237}
238
239
240void
241pmap_hash_lock(int entry)
242{
243	int attempt = 0;
244	int locked = 0;
245	do {
246		if (pmap_hash_lock_word & (1 << entry)) {
247			attempt++;
248			if(attempt >0x20000000)
249				panic("unable to obtain lock on entry %d",
250				    entry);
251			continue;
252		}
253		locked = pmap_hash_lock_try(entry);
254	} while (locked == 0);
255}
256
257void
258pmap_hash_unlock(int entry)
259{
260	atomic_clearbits_int(&pmap_hash_lock_word,  1 << entry);
261}
262
263/* virtual to physical helpers */
264static inline int
265VP_SR(vaddr_t va)
266{
267	return (va >>VP_SR_POS) & VP_SR_MASK;
268}
269
270static inline int
271VP_IDX1(vaddr_t va)
272{
273	return (va >> VP_IDX1_POS) & VP_IDX1_MASK;
274}
275
276static inline int
277VP_IDX2(vaddr_t va)
278{
279	return (va >> VP_IDX2_POS) & VP_IDX2_MASK;
280}
281
282#if VP_IDX1_SIZE != VP_IDX2_SIZE
283#error pmap allocation code expects IDX1 and IDX2 size to be same
284#endif
285struct pmapvp {
286	void *vp[VP_IDX1_SIZE];
287};
288
289
290/*
291 * VP routines, virtual to physical translation information.
292 * These data structures are based off of the pmap, per process.
293 */
294
295/*
296 * This is used for pmap_kernel() mappings, they are not to be removed
297 * from the vp table because they were statically initialized at the
298 * initial pmap initialization. This is so that memory allocation
299 * is not necessary in the pmap_kernel() mappings.
300 * Otherwise bad race conditions can appear.
301 */
302struct pte_desc *
303pmap_vp_lookup(pmap_t pm, vaddr_t va)
304{
305	struct pmapvp *vp1;
306	struct pmapvp *vp2;
307	struct pte_desc *pted;
308
309	vp1 = pm->pm_vp[VP_SR(va)];
310	if (vp1 == NULL) {
311		return NULL;
312	}
313
314	vp2 = vp1->vp[VP_IDX1(va)];
315	if (vp2 == NULL) {
316		return NULL;
317	}
318
319	pted = vp2->vp[VP_IDX2(va)];
320
321	return pted;
322}
323
324/*
325 * Remove, and return, pted at specified address, NULL if not present
326 */
327struct pte_desc *
328pmap_vp_remove(pmap_t pm, vaddr_t va)
329{
330	struct pmapvp *vp1;
331	struct pmapvp *vp2;
332	struct pte_desc *pted;
333
334	vp1 = pm->pm_vp[VP_SR(va)];
335	if (vp1 == NULL) {
336		return NULL;
337	}
338
339	vp2 = vp1->vp[VP_IDX1(va)];
340	if (vp2 == NULL) {
341		return NULL;
342	}
343
344	pted = vp2->vp[VP_IDX2(va)];
345	vp2->vp[VP_IDX2(va)] = NULL;
346
347	return pted;
348}
349
350/*
351 * Create a V -> P mapping for the given pmap and virtual address
352 * with reference to the pte descriptor that is used to map the page.
353 * This code should track allocations of vp table allocations
354 * so they can be freed efficiently.
355 *
356 * Should this be called under splvm?
357 */
358int
359pmap_vp_enter(pmap_t pm, vaddr_t va, struct pte_desc *pted, int flags)
360{
361	struct pmapvp *vp1;
362	struct pmapvp *vp2;
363
364	pmap_simplelock_pm(pm);
365
366	vp1 = pm->pm_vp[VP_SR(va)];
367	if (vp1 == NULL) {
368		vp1 = pool_get(&pmap_vp_pool, PR_NOWAIT | PR_ZERO);
369		if (vp1 == NULL) {
370			if ((flags & PMAP_CANFAIL) == 0)
371				panic("pmap_vp_enter: failed to allocate vp1");
372			return ENOMEM;
373		}
374		pm->pm_vp[VP_SR(va)] = vp1;
375	}
376
377	vp2 = vp1->vp[VP_IDX1(va)];
378	if (vp2 == NULL) {
379		vp2 = pool_get(&pmap_vp_pool, PR_NOWAIT | PR_ZERO);
380		if (vp2 == NULL) {
381			if ((flags & PMAP_CANFAIL) == 0)
382				panic("pmap_vp_enter: failed to allocate vp2");
383			return ENOMEM;
384		}
385		vp1->vp[VP_IDX1(va)] = vp2;
386	}
387
388	vp2->vp[VP_IDX2(va)] = pted;
389
390	pmap_simpleunlock_pm(pm);
391
392	return 0;
393}
394
395/* PTE manipulation/calculations */
396static inline void
397tlbie(vaddr_t va)
398{
399	__asm volatile ("tlbie %0" :: "r"(va));
400}
401
402static inline void
403tlbsync(void)
404{
405	__asm volatile ("sync; tlbsync; sync");
406}
407
408void
409tlbia()
410{
411	vaddr_t va;
412
413	__asm volatile ("sync");
414	for (va = 0; va < 0x00040000; va += 0x00001000)
415		tlbie(va);
416	tlbsync();
417}
418
419static inline int
420ptesr(sr_t *sr, vaddr_t va)
421{
422	return sr[(u_int)va >> ADDR_SR_SHIFT];
423}
424
425static inline int
426pteidx(sr_t sr, vaddr_t va)
427{
428	int hash;
429	hash = (sr & SR_VSID) ^ (((u_int)va & ADDR_PIDX) >> ADDR_PIDX_SHIFT);
430	return hash & pmap_ptab_mask;
431}
432
433#define PTED_VA_PTEGIDX_M	0x07
434#define PTED_VA_HID_M		0x08
435#define PTED_VA_MANAGED_M	0x10
436#define PTED_VA_WIRED_M		0x20
437#define PTED_VA_EXEC_M		0x40
438
439static inline u_int32_t
440PTED_HID(struct pte_desc *pted)
441{
442	return (pted->pted_va & PTED_VA_HID_M);
443}
444
445static inline u_int32_t
446PTED_PTEGIDX(struct pte_desc *pted)
447{
448	return (pted->pted_va & PTED_VA_PTEGIDX_M);
449}
450
451static inline u_int32_t
452PTED_MANAGED(struct pte_desc *pted)
453{
454	return (pted->pted_va & PTED_VA_MANAGED_M);
455}
456
457static inline u_int32_t
458PTED_WIRED(struct pte_desc *pted)
459{
460	return (pted->pted_va & PTED_VA_WIRED_M);
461}
462
463static inline u_int32_t
464PTED_VALID(struct pte_desc *pted)
465{
466	if (ppc_proc_is_64b)
467		return (pted->p.pted_pte64.pte_hi & PTE_VALID_64);
468	else
469		return (pted->p.pted_pte32.pte_hi & PTE_VALID_32);
470}
471
472/*
473 * PV entries -
474 * manipulate the physical to virtual translations for the entire system.
475 *
476 * QUESTION: should all mapped memory be stored in PV tables? Or
477 * is it alright to only store "ram" memory. Currently device mappings
478 * are not stored.
479 * It makes sense to pre-allocate mappings for all of "ram" memory, since
480 * it is likely that it will be mapped at some point, but would it also
481 * make sense to use a tree/table like is use for pmap to store device
482 * mappings?
483 * Further notes: It seems that the PV table is only used for pmap_protect
484 * and other paging related operations. Given this, it is not necessary
485 * to store any pmap_kernel() entries in PV tables and does not make
486 * sense to store device mappings in PV either.
487 *
488 * Note: unlike other powerpc pmap designs, the array is only an array
489 * of pointers. Since the same structure is used for holding information
490 * in the VP table, the PV table, and for kernel mappings, the wired entries.
491 * Allocate one data structure to hold all of the info, instead of replicating
492 * it multiple times.
493 *
494 * One issue of making this a single data structure is that two pointers are
495 * wasted for every page which does not map ram (device mappings), this
496 * should be a low percentage of mapped pages in the system, so should not
497 * have too noticable unnecessary ram consumption.
498 */
499
500void
501pmap_enter_pv(struct pte_desc *pted, struct vm_page *pg)
502{
503	if (__predict_false(!pmap_initialized)) {
504		return;
505	}
506
507	LIST_INSERT_HEAD(&(pg->mdpage.pv_list), pted, pted_pv_list);
508	pted->pted_va |= PTED_VA_MANAGED_M;
509}
510
511void
512pmap_remove_pv(struct pte_desc *pted)
513{
514	LIST_REMOVE(pted, pted_pv_list);
515}
516
517
518/* PTE_CHG_32 == PTE_CHG_64 */
519/* PTE_REF_32 == PTE_REF_64 */
520static __inline u_int
521pmap_pte2flags(u_int32_t pte)
522{
523	return (((pte & PTE_REF_32) ? PG_PMAP_REF : 0) |
524	    ((pte & PTE_CHG_32) ? PG_PMAP_MOD : 0));
525}
526
527static __inline u_int
528pmap_flags2pte(u_int32_t flags)
529{
530	return (((flags & PG_PMAP_REF) ? PTE_REF_32 : 0) |
531	    ((flags & PG_PMAP_MOD) ? PTE_CHG_32 : 0));
532}
533
534void
535pmap_attr_save(paddr_t pa, u_int32_t bits)
536{
537	struct vm_page *pg;
538
539	pg = PHYS_TO_VM_PAGE(pa);
540	if (pg == NULL)
541		return;
542
543	atomic_setbits_int(&pg->pg_flags,  pmap_pte2flags(bits));
544}
545
546int
547pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
548{
549	struct pte_desc *pted;
550	struct vm_page *pg;
551	boolean_t nocache = (pa & PMAP_NOCACHE) != 0;
552	int s;
553	int need_sync = 0;
554	int cache;
555	int error;
556
557	/* MP - Acquire lock for this pmap */
558
559	s = splvm();
560	pted = pmap_vp_lookup(pm, va);
561	if (pted && PTED_VALID(pted)) {
562		pmap_remove_pg(pm, va);
563		/* we lost our pted if it was user */
564		if (pm != pmap_kernel())
565			pted = pmap_vp_lookup(pm, va);
566	}
567
568	pm->pm_stats.resident_count++;
569
570	/* Do not have pted for this, get one and put it in VP */
571	if (pted == NULL) {
572		pted = pool_get(&pmap_pted_pool, PR_NOWAIT | PR_ZERO);
573		if (pted == NULL) {
574			if ((flags & PMAP_CANFAIL) == 0) {
575				splx(s);
576				return ENOMEM;
577			}
578			panic("pmap_enter: failed to allocate pted");
579		}
580		error = pmap_vp_enter(pm, va, pted, flags);
581		if (error) {
582			pool_put(&pmap_pted_pool, pted);
583			splx(s);
584			return error;
585		}
586	}
587
588	pa &= PMAP_PA_MASK;
589
590	/* Calculate PTE */
591	pg = PHYS_TO_VM_PAGE(pa);
592	if (pg != NULL && !nocache)
593		cache = PMAP_CACHE_WB; /* managed memory is cacheable */
594	else
595		cache = PMAP_CACHE_CI;
596
597	if (ppc_proc_is_64b)
598		pmap_fill_pte64(pm, va, pa, pted, prot, flags, cache);
599	else
600		pmap_fill_pte32(pm, va, pa, pted, prot, flags, cache);
601
602	if (pg != NULL) {
603		pmap_enter_pv(pted, pg); /* only managed mem */
604	}
605
606	/*
607	 * Insert into HTAB
608	 * We were told to map the page, probably called from vm_fault,
609	 * so map the page!
610	 */
611	if (ppc_proc_is_64b)
612		pte_insert64(pted);
613	else
614		pte_insert32(pted);
615
616        if (prot & VM_PROT_EXECUTE) {
617		u_int sn = VP_SR(va);
618
619        	pm->pm_exec[sn]++;
620		if (pm->pm_sr[sn] & SR_NOEXEC)
621			pm->pm_sr[sn] &= ~SR_NOEXEC;
622
623		if (pg != NULL) {
624			need_sync = ((pg->pg_flags & PG_PMAP_EXE) == 0);
625			if (prot & VM_PROT_WRITE)
626				atomic_clearbits_int(&pg->pg_flags,
627				    PG_PMAP_EXE);
628			else
629				atomic_setbits_int(&pg->pg_flags,
630				    PG_PMAP_EXE);
631		} else
632			need_sync = 1;
633	} else {
634		/*
635		 * Should we be paranoid about writeable non-exec
636		 * mappings ? if so, clear the exec tag
637		 */
638		if ((prot & VM_PROT_WRITE) && (pg != NULL))
639			atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE);
640	}
641
642	splx(s);
643
644	/* only instruction sync executable pages */
645	if (need_sync)
646		pmap_syncicache_user_virt(pm, va);
647
648	/* MP - free pmap lock */
649	return 0;
650}
651
652/*
653 * Remove the given range of mapping entries.
654 */
655void
656pmap_remove(pmap_t pm, vaddr_t va, vaddr_t endva)
657{
658	int i_sr, s_sr, e_sr;
659	int i_vp1, s_vp1, e_vp1;
660	int i_vp2, s_vp2, e_vp2;
661	struct pmapvp *vp1;
662	struct pmapvp *vp2;
663
664	/* I suspect that if this loop were unrolled better
665	 * it would have better performance, testing i_sr and i_vp1
666	 * in the middle loop seems excessive
667	 */
668
669	s_sr = VP_SR(va);
670	e_sr = VP_SR(endva);
671	for (i_sr = s_sr; i_sr <= e_sr; i_sr++) {
672		vp1 = pm->pm_vp[i_sr];
673		if (vp1 == NULL)
674			continue;
675
676		if (i_sr == s_sr)
677			s_vp1 = VP_IDX1(va);
678		else
679			s_vp1 = 0;
680
681		if (i_sr == e_sr)
682			e_vp1 = VP_IDX1(endva);
683		else
684			e_vp1 = VP_IDX1_SIZE-1;
685
686		for (i_vp1 = s_vp1; i_vp1 <= e_vp1; i_vp1++) {
687			vp2 = vp1->vp[i_vp1];
688			if (vp2 == NULL)
689				continue;
690
691			if ((i_sr == s_sr) && (i_vp1 == s_vp1))
692				s_vp2 = VP_IDX2(va);
693			else
694				s_vp2 = 0;
695
696			if ((i_sr == e_sr) && (i_vp1 == e_vp1))
697				e_vp2 = VP_IDX2(endva);
698			else
699				e_vp2 = VP_IDX2_SIZE;
700
701			for (i_vp2 = s_vp2; i_vp2 < e_vp2; i_vp2++) {
702				if (vp2->vp[i_vp2] != NULL) {
703					pmap_remove_pg(pm,
704					    (i_sr << VP_SR_POS) |
705					    (i_vp1 << VP_IDX1_POS) |
706					    (i_vp2 << VP_IDX2_POS));
707				}
708			}
709		}
710	}
711}
712/*
713 * remove a single mapping, notice that this code is O(1)
714 */
715void
716pmap_remove_pg(pmap_t pm, vaddr_t va)
717{
718	struct pte_desc *pted;
719	int s;
720
721	/*
722	 * HASH needs to be locked here as well as pmap, and pv list.
723	 * so that we know the mapping information is either valid,
724	 * or that the mapping is not present in the hash table.
725	 */
726	s = splvm();
727	if (pm == pmap_kernel()) {
728		pted = pmap_vp_lookup(pm, va);
729		if (pted == NULL || !PTED_VALID(pted)) {
730			splx(s);
731			return;
732		}
733	} else {
734		pted = pmap_vp_remove(pm, va);
735		if (pted == NULL || !PTED_VALID(pted)) {
736			splx(s);
737			return;
738		}
739	}
740	pm->pm_stats.resident_count--;
741
742	pmap_hash_remove(pted);
743
744	if (pted->pted_va & PTED_VA_EXEC_M) {
745		u_int sn = VP_SR(va);
746
747		pted->pted_va &= ~PTED_VA_EXEC_M;
748		pm->pm_exec[sn]--;
749		if (pm->pm_exec[sn] == 0)
750			pm->pm_sr[sn] |= SR_NOEXEC;
751	}
752
753	if (ppc_proc_is_64b)
754		pted->p.pted_pte64.pte_hi &= ~PTE_VALID_64;
755	else
756		pted->p.pted_pte32.pte_hi &= ~PTE_VALID_32;
757
758	if (PTED_MANAGED(pted))
759		pmap_remove_pv(pted);
760
761	if (pm != pmap_kernel())
762		pool_put(&pmap_pted_pool, pted);
763
764	splx(s);
765}
766
767/*
768 * Enter a kernel mapping for the given page.
769 * kernel mappings have a larger set of prerequisites than normal mappings.
770 *
771 * 1. no memory should be allocated to create a kernel mapping.
772 * 2. a vp mapping should already exist, even if invalid. (see 1)
773 * 3. all vp tree mappings should already exist (see 1)
774 *
775 */
776void
777_pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, int flags, int cache)
778{
779	struct pte_desc *pted;
780	struct vm_page *pg;
781	int s;
782	pmap_t pm;
783
784	pm = pmap_kernel();
785
786	/* MP - lock pmap. */
787	s = splvm();
788
789	pted = pmap_vp_lookup(pm, va);
790	if (pted && PTED_VALID(pted))
791		pmap_kremove_pg(va); /* pted is reused */
792
793	pm->pm_stats.resident_count++;
794	if (prot & VM_PROT_WRITE) {
795		pg = PHYS_TO_VM_PAGE(pa);
796		if (pg != NULL)
797			atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE);
798	}
799
800	/* Do not have pted for this, get one and put it in VP */
801	if (pted == NULL) {
802		panic("pted not preallocated in pmap_kernel() va %lx pa %lx",
803		    va, pa);
804	}
805
806	if (cache == PMAP_CACHE_DEFAULT) {
807		pg = PHYS_TO_VM_PAGE(pa);
808		if (pg != NULL && (pg->pg_flags & PG_DEV) == 0)
809			cache = PMAP_CACHE_WB;
810		else
811			cache = PMAP_CACHE_CI;
812	}
813
814	/* Calculate PTE */
815	if (ppc_proc_is_64b)
816		pmap_fill_pte64(pm, va, pa, pted, prot, flags, cache);
817	else
818		pmap_fill_pte32(pm, va, pa, pted, prot, flags, cache);
819
820	/*
821	 * Insert into HTAB
822	 * We were told to map the page, probably called from vm_fault,
823	 * so map the page!
824	 */
825	if (ppc_proc_is_64b)
826		pte_insert64(pted);
827	else
828		pte_insert32(pted);
829
830	pted->pted_va |= PTED_VA_WIRED_M;
831
832        if (prot & VM_PROT_EXECUTE) {
833		u_int sn = VP_SR(va);
834
835        	pm->pm_exec[sn]++;
836		if (pm->pm_sr[sn] & SR_NOEXEC)
837			pm->pm_sr[sn] &= ~SR_NOEXEC;
838	}
839
840	splx(s);
841}
842
843void
844pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
845{
846	_pmap_kenter_pa(va, pa, prot, 0, PMAP_CACHE_DEFAULT);
847}
848
849void
850pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable)
851{
852	_pmap_kenter_pa(va, pa, prot, 0, cacheable);
853}
854
855
856/*
857 * remove kernel (pmap_kernel()) mapping, one page
858 */
859void
860pmap_kremove_pg(vaddr_t va)
861{
862	struct pte_desc *pted;
863	pmap_t pm;
864	int s;
865
866	pm = pmap_kernel();
867	pted = pmap_vp_lookup(pm, va);
868	if (pted == NULL)
869		return;
870
871	if (!PTED_VALID(pted))
872		return; /* not mapped */
873
874	s = splvm();
875
876	pm->pm_stats.resident_count--;
877
878	/*
879	 * HASH needs to be locked here as well as pmap, and pv list.
880	 * so that we know the mapping information is either valid,
881	 * or that the mapping is not present in the hash table.
882	 */
883	pmap_hash_remove(pted);
884
885	if (pted->pted_va & PTED_VA_EXEC_M) {
886		u_int sn = VP_SR(va);
887
888		pted->pted_va &= ~PTED_VA_EXEC_M;
889		pm->pm_exec[sn]--;
890		if (pm->pm_exec[sn] == 0)
891			pm->pm_sr[sn] |= SR_NOEXEC;
892	}
893
894	if (PTED_MANAGED(pted))
895		pmap_remove_pv(pted);
896
897	/* invalidate pted; */
898	if (ppc_proc_is_64b)
899		pted->p.pted_pte64.pte_hi &= ~PTE_VALID_64;
900	else
901		pted->p.pted_pte32.pte_hi &= ~PTE_VALID_32;
902
903	splx(s);
904
905}
906/*
907 * remove kernel (pmap_kernel()) mappings
908 */
909void
910pmap_kremove(vaddr_t va, vsize_t len)
911{
912	for (len >>= PAGE_SHIFT; len >0; len--, va += PAGE_SIZE)
913		pmap_kremove_pg(va);
914}
915
916void
917pte_zap(void *ptp, struct pte_desc *pted)
918{
919
920	struct pte_64 *ptp64 = (void*) ptp;
921	struct pte_32 *ptp32 = (void*) ptp;
922
923	if (ppc_proc_is_64b)
924		ptp64->pte_hi &= ~PTE_VALID_64;
925	else
926		ptp32->pte_hi &= ~PTE_VALID_32;
927
928	__asm volatile ("sync");
929	tlbie(pted->pted_va);
930	__asm volatile ("sync");
931	tlbsync();
932	__asm volatile ("sync");
933	if (ppc_proc_is_64b) {
934		if (PTED_MANAGED(pted))
935			pmap_attr_save(pted->p.pted_pte64.pte_lo & PTE_RPGN_64,
936			    ptp64->pte_lo & (PTE_REF_64|PTE_CHG_64));
937	} else {
938		if (PTED_MANAGED(pted))
939			pmap_attr_save(pted->p.pted_pte32.pte_lo & PTE_RPGN_32,
940			    ptp32->pte_lo & (PTE_REF_32|PTE_CHG_32));
941	}
942}
943
944/*
945 * remove specified entry from hash table.
946 * all information is present in pted to look up entry
947 * LOCKS... should the caller lock?
948 */
949void
950pmap_hash_remove(struct pte_desc *pted)
951{
952	vaddr_t va = pted->pted_va;
953	pmap_t pm = pted->pted_pmap;
954	struct pte_64 *ptp64;
955	struct pte_32 *ptp32;
956	int sr, idx;
957	int s;
958
959	sr = ptesr(pm->pm_sr, va);
960	idx = pteidx(sr, va);
961
962	idx =  (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0));
963	/* determine which pteg mapping is present in */
964
965	if (ppc_proc_is_64b) {
966		int entry = PTED_PTEGIDX(pted);
967		ptp64 = pmap_ptable64 + (idx * 8);
968		ptp64 += entry; /* increment by entry into pteg */
969		s = ppc_intr_disable();
970		pmap_hash_lock(entry);
971		/*
972		 * We now have the pointer to where it will be, if it is
973		 * currently mapped. If the mapping was thrown away in
974		 * exchange for another page mapping, then this page is not
975		 * currently in the HASH.
976		 */
977		if ((pted->p.pted_pte64.pte_hi |
978		    (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi) {
979			pte_zap((void*)ptp64, pted);
980		}
981		pmap_hash_unlock(entry);
982		ppc_intr_enable(s);
983	} else {
984		int entry = PTED_PTEGIDX(pted);
985		ptp32 = pmap_ptable32 + (idx * 8);
986		ptp32 += entry; /* increment by entry into pteg */
987		s = ppc_intr_disable();
988		pmap_hash_lock(entry);
989		/*
990		 * We now have the pointer to where it will be, if it is
991		 * currently mapped. If the mapping was thrown away in
992		 * exchange for another page mapping, then this page is not
993		 * currently in the HASH.
994		 */
995		if ((pted->p.pted_pte32.pte_hi |
996		    (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi) {
997			pte_zap((void*)ptp32, pted);
998		}
999		pmap_hash_unlock(entry);
1000		ppc_intr_enable(s);
1001	}
1002}
1003
1004/*
1005 * What about execution control? Even at only a segment granularity.
1006 */
1007void
1008pmap_fill_pte64(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted,
1009	vm_prot_t prot, int flags, int cache)
1010{
1011	sr_t sr;
1012	struct pte_64 *pte64;
1013
1014	sr = ptesr(pm->pm_sr, va);
1015	pte64 = &pted->p.pted_pte64;
1016
1017	pte64->pte_hi = (((u_int64_t)sr & SR_VSID) <<
1018	   PTE_VSID_SHIFT_64) |
1019	    ((va >> ADDR_API_SHIFT_64) & PTE_API_64) | PTE_VALID_64;
1020	pte64->pte_lo = (pa & PTE_RPGN_64);
1021
1022
1023	if (cache == PMAP_CACHE_WB)
1024		pte64->pte_lo |= PTE_M_64;
1025	else if (cache == PMAP_CACHE_WT)
1026		pte64->pte_lo |= (PTE_W_64 | PTE_M_64);
1027	else
1028		pte64->pte_lo |= (PTE_M_64 | PTE_I_64 | PTE_G_64);
1029
1030	if (prot & VM_PROT_WRITE)
1031		pte64->pte_lo |= PTE_RW_64;
1032	else
1033		pte64->pte_lo |= PTE_RO_64;
1034
1035	pted->pted_va = va & ~PAGE_MASK;
1036
1037	if (prot & VM_PROT_EXECUTE)
1038		pted->pted_va  |= PTED_VA_EXEC_M;
1039	else
1040		pte64->pte_lo |= PTE_N_64;
1041
1042	pted->pted_pmap = pm;
1043}
1044/*
1045 * What about execution control? Even at only a segment granularity.
1046 */
1047void
1048pmap_fill_pte32(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted,
1049	vm_prot_t prot, int flags, int cache)
1050{
1051	sr_t sr;
1052	struct pte_32 *pte32;
1053
1054	sr = ptesr(pm->pm_sr, va);
1055	pte32 = &pted->p.pted_pte32;
1056
1057	pte32->pte_hi = ((sr & SR_VSID) << PTE_VSID_SHIFT_32) |
1058	    ((va >> ADDR_API_SHIFT_32) & PTE_API_32) | PTE_VALID_32;
1059	pte32->pte_lo = (pa & PTE_RPGN_32);
1060
1061	if (cache == PMAP_CACHE_WB)
1062		pte32->pte_lo |= PTE_M_32;
1063	else if (cache == PMAP_CACHE_WT)
1064		pte32->pte_lo |= (PTE_W_32 | PTE_M_32);
1065	else
1066		pte32->pte_lo |= (PTE_M_32 | PTE_I_32 | PTE_G_32);
1067
1068	if (prot & VM_PROT_WRITE)
1069		pte32->pte_lo |= PTE_RW_32;
1070	else
1071		pte32->pte_lo |= PTE_RO_32;
1072
1073	pted->pted_va = va & ~PAGE_MASK;
1074
1075	/* XXX Per-page execution control. */
1076	if (prot & VM_PROT_EXECUTE)
1077		pted->pted_va  |= PTED_VA_EXEC_M;
1078
1079	pted->pted_pmap = pm;
1080}
1081
1082/*
1083 * read/clear bits from pte/attr cache, for reference/change
1084 * ack, copied code in the pte flush code....
1085 */
1086int
1087pteclrbits(struct vm_page *pg, u_int flagbit, u_int clear)
1088{
1089	u_int bits;
1090	int s;
1091	struct pte_desc *pted;
1092	u_int ptebit = pmap_flags2pte(flagbit);
1093
1094	/* PTE_CHG_32 == PTE_CHG_64 */
1095	/* PTE_REF_32 == PTE_REF_64 */
1096
1097	/*
1098	 *  First try the attribute cache
1099	 */
1100	bits = pg->pg_flags & flagbit;
1101	if ((bits == flagbit) && (clear == 0))
1102		return bits;
1103
1104	/* cache did not contain all necessary bits,
1105	 * need to walk thru pv table to collect all mappings for this
1106	 * page, copying bits to the attribute cache
1107	 * then reread the attribute cache.
1108	 */
1109	/* need lock for this pv */
1110	s = splvm();
1111
1112	LIST_FOREACH(pted, &(pg->mdpage.pv_list), pted_pv_list) {
1113		vaddr_t va = pted->pted_va & PAGE_MASK;
1114		pmap_t pm = pted->pted_pmap;
1115		struct pte_64 *ptp64;
1116		struct pte_32 *ptp32;
1117		int sr, idx;
1118
1119		sr = ptesr(pm->pm_sr, va);
1120		idx = pteidx(sr, va);
1121
1122		/* determine which pteg mapping is present in */
1123		if (ppc_proc_is_64b) {
1124			ptp64 = pmap_ptable64 +
1125				(idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8;
1126			ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */
1127
1128			/*
1129			 * We now have the pointer to where it will be, if it is
1130			 * currently mapped. If the mapping was thrown away in
1131			 * exchange for another page mapping, then this page is
1132			 * not currently in the HASH.
1133			 *
1134			 * if we are not clearing bits, and have found all of the
1135			 * bits we want, we can stop
1136			 */
1137			if ((pted->p.pted_pte64.pte_hi |
1138			    (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi) {
1139				bits |=	pmap_pte2flags(ptp64->pte_lo & ptebit);
1140				if (clear) {
1141					ptp64->pte_hi &= ~PTE_VALID_64;
1142					__asm__ volatile ("sync");
1143					tlbie(va);
1144					tlbsync();
1145					ptp64->pte_lo &= ~ptebit;
1146					__asm__ volatile ("sync");
1147					ptp64->pte_hi |= PTE_VALID_64;
1148				} else if (bits == flagbit)
1149					break;
1150			}
1151		} else {
1152			ptp32 = pmap_ptable32 +
1153				(idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8;
1154			ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */
1155
1156			/*
1157			 * We now have the pointer to where it will be, if it is
1158			 * currently mapped. If the mapping was thrown away in
1159			 * exchange for another page mapping, then this page is
1160			 * not currently in the HASH.
1161			 *
1162			 * if we are not clearing bits, and have found all of the
1163			 * bits we want, we can stop
1164			 */
1165			if ((pted->p.pted_pte32.pte_hi |
1166			    (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi) {
1167				bits |=	pmap_pte2flags(ptp32->pte_lo & ptebit);
1168				if (clear) {
1169					ptp32->pte_hi &= ~PTE_VALID_32;
1170					__asm__ volatile ("sync");
1171					tlbie(va);
1172					tlbsync();
1173					ptp32->pte_lo &= ~ptebit;
1174					__asm__ volatile ("sync");
1175					ptp32->pte_hi |= PTE_VALID_32;
1176				} else if (bits == flagbit)
1177					break;
1178			}
1179		}
1180	}
1181
1182	if (clear) {
1183		/*
1184		 * this is done a second time, because while walking the list
1185		 * a bit could have been promoted via pmap_attr_save()
1186		 */
1187		bits |= pg->pg_flags & flagbit;
1188		atomic_clearbits_int(&pg->pg_flags,  flagbit);
1189	} else
1190		atomic_setbits_int(&pg->pg_flags,  bits);
1191
1192	splx(s);
1193	return bits;
1194}
1195
1196/*
1197 * Garbage collects the physical map system for pages which are
1198 * no longer used. Success need not be guaranteed -- that is, there
1199 * may well be pages which are not referenced, but others may be collected
1200 * Called by the pageout daemon when pages are scarce.
1201 */
1202void
1203pmap_collect(pmap_t pm)
1204{
1205	/* This could return unused v->p table layers which
1206	 * are empty.
1207	 * could malicious programs allocate memory and eat
1208	 * these wired pages? These are allocated via pool.
1209	 * Are there pool functions which could be called
1210	 * to lower the pool usage here?
1211	 */
1212}
1213
1214/*
1215 * Fill the given physical page with zeros.
1216 */
1217void
1218pmap_zero_page(struct vm_page *pg)
1219{
1220	paddr_t pa = VM_PAGE_TO_PHYS(pg);
1221#ifdef USE_DCBZ
1222	int i;
1223	paddr_t addr = zero_page;
1224#endif
1225
1226	/* simple_lock(&pmap_zero_page_lock); */
1227	pmap_kenter_pa(zero_page, pa, VM_PROT_READ|VM_PROT_WRITE);
1228#ifdef USE_DCBZ
1229	for (i = PAGE_SIZE/CACHELINESIZE; i>0; i--) {
1230		__asm volatile ("dcbz 0,%0" :: "r"(addr));
1231		addr += CACHELINESIZE;
1232	}
1233#else
1234	bzero((void *)zero_page, PAGE_SIZE);
1235#endif
1236	pmap_kremove_pg(zero_page);
1237
1238	/* simple_unlock(&pmap_zero_page_lock); */
1239}
1240
1241/*
1242 * copy the given physical page with zeros.
1243 */
1244void
1245pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
1246{
1247	paddr_t srcpa = VM_PAGE_TO_PHYS(srcpg);
1248	paddr_t dstpa = VM_PAGE_TO_PHYS(dstpg);
1249	/* simple_lock(&pmap_copy_page_lock); */
1250
1251	pmap_kenter_pa(copy_src_page, srcpa, VM_PROT_READ);
1252	pmap_kenter_pa(copy_dst_page, dstpa, VM_PROT_READ|VM_PROT_WRITE);
1253
1254	bcopy((void *)copy_src_page, (void *)copy_dst_page, PAGE_SIZE);
1255
1256	pmap_kremove_pg(copy_src_page);
1257	pmap_kremove_pg(copy_dst_page);
1258	/* simple_unlock(&pmap_copy_page_lock); */
1259}
1260
1261int pmap_id_avail = 0;
1262
1263void
1264pmap_pinit(pmap_t pm)
1265{
1266	int i, k, try, tblidx, tbloff;
1267	int s, seg;
1268
1269	bzero(pm, sizeof (struct pmap));
1270
1271	pmap_reference(pm);
1272
1273	/*
1274	 * Allocate segment registers for this pmap.
1275	 * Try not to reuse pmap ids, to spread the hash table usage.
1276	 */
1277again:
1278	for (i = 0; i < NPMAPS; i++) {
1279		try = pmap_id_avail + i;
1280		try = try % NPMAPS; /* truncate back into bounds */
1281		tblidx = try / (8 * sizeof usedsr[0]);
1282		tbloff = try % (8 * sizeof usedsr[0]);
1283		if ((usedsr[tblidx] & (1 << tbloff)) == 0) {
1284			/* pmap create lock? */
1285			s = splvm();
1286			if ((usedsr[tblidx] & (1 << tbloff)) == 1) {
1287				/* entry was stolen out from under us, retry */
1288				splx(s); /* pmap create unlock */
1289				goto again;
1290			}
1291			usedsr[tblidx] |= (1 << tbloff);
1292			pmap_id_avail = try + 1;
1293			splx(s); /* pmap create unlock */
1294
1295			seg = try << 4;
1296			for (k = 0; k < 16; k++)
1297				pm->pm_sr[k] = (seg + k) | SR_NOEXEC;
1298			return;
1299		}
1300	}
1301	panic("out of pmap slots");
1302}
1303
1304/*
1305 * Create and return a physical map.
1306 */
1307pmap_t
1308pmap_create()
1309{
1310	pmap_t pmap;
1311
1312	pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);
1313	pmap_pinit(pmap);
1314	return (pmap);
1315}
1316
1317/*
1318 * Add a reference to a given pmap.
1319 */
1320void
1321pmap_reference(pmap_t pm)
1322{
1323	/* simple_lock(&pmap->pm_obj.vmobjlock); */
1324	pm->pm_refs++;
1325	/* simple_unlock(&pmap->pm_obj.vmobjlock); */
1326}
1327
1328/*
1329 * Retire the given pmap from service.
1330 * Should only be called if the map contains no valid mappings.
1331 */
1332void
1333pmap_destroy(pmap_t pm)
1334{
1335	int refs;
1336
1337	/* simple_lock(&pmap->pm_obj.vmobjlock); */
1338	refs = --pm->pm_refs;
1339	/* simple_unlock(&pmap->pm_obj.vmobjlock); */
1340	if (refs > 0)
1341		return;
1342
1343	/*
1344	 * reference count is zero, free pmap resources and free pmap.
1345	 */
1346	pmap_release(pm);
1347	pool_put(&pmap_pmap_pool, pm);
1348}
1349
1350/*
1351 * Release any resources held by the given physical map.
1352 * Called when a pmap initialized by pmap_pinit is being released.
1353 */
1354void
1355pmap_release(pmap_t pm)
1356{
1357	int i, tblidx, tbloff;
1358	int s;
1359
1360	pmap_vp_destroy(pm);
1361	i = (pm->pm_sr[0] & SR_VSID) >> 4;
1362	tblidx = i / (8  * sizeof usedsr[0]);
1363	tbloff = i % (8  * sizeof usedsr[0]);
1364
1365	/* LOCK? */
1366	s = splvm();
1367	usedsr[tblidx] &= ~(1 << tbloff);
1368	splx(s);
1369}
1370
1371void
1372pmap_vp_destroy(pmap_t pm)
1373{
1374	int i, j;
1375	struct pmapvp *vp1;
1376	struct pmapvp *vp2;
1377
1378	for (i = 0; i < VP_SR_SIZE; i++) {
1379		vp1 = pm->pm_vp[i];
1380		if (vp1 == NULL)
1381			continue;
1382
1383		for (j = 0; j < VP_IDX1_SIZE; j++) {
1384			vp2 = vp1->vp[j];
1385			if (vp2 == NULL)
1386				continue;
1387
1388			pool_put(&pmap_vp_pool, vp2);
1389		}
1390		pm->pm_vp[i] = NULL;
1391		pool_put(&pmap_vp_pool, vp1);
1392	}
1393}
1394
1395void
1396pmap_avail_setup(void)
1397{
1398	struct mem_region *mp;
1399	int pmap_physmem;
1400
1401	(fw->mem_regions) (&pmap_mem, &pmap_avail);
1402	pmap_cnt_avail = 0;
1403	pmap_physmem = 0;
1404
1405	ndumpmem = 0;
1406	for (mp = pmap_mem; mp->size !=0; mp++, ndumpmem++) {
1407		pmap_physmem += atop(mp->size);
1408		dumpmem[ndumpmem].start = atop(mp->start);
1409		dumpmem[ndumpmem].end = atop(mp->start + mp->size);
1410	}
1411
1412	if (physmem == 0)
1413		physmem = pmap_physmem;
1414
1415	for (mp = pmap_avail; mp->size !=0 ; mp++) {
1416		if (physmaxaddr <  mp->start + mp->size)
1417			physmaxaddr = mp->start + mp->size;
1418	}
1419
1420	for (mp = pmap_avail; mp->size !=0; mp++)
1421		pmap_cnt_avail += 1;
1422}
1423
1424void
1425pmap_avail_fixup(void)
1426{
1427	struct mem_region *mp;
1428	u_int32_t align;
1429	u_int32_t end;
1430
1431	mp = pmap_avail;
1432	while(mp->size !=0) {
1433		align = round_page(mp->start);
1434		if (mp->start != align) {
1435			pmap_remove_avail(mp->start, align);
1436			mp = pmap_avail;
1437			continue;
1438		}
1439		end = mp->start+mp->size;
1440		align = trunc_page(end);
1441		if (end != align) {
1442			pmap_remove_avail(align, end);
1443			mp = pmap_avail;
1444			continue;
1445		}
1446		mp++;
1447	}
1448}
1449
1450/* remove a given region from avail memory */
1451void
1452pmap_remove_avail(paddr_t base, paddr_t end)
1453{
1454	struct mem_region *mp;
1455	int i;
1456	int mpend;
1457
1458	/* remove given region from available */
1459	for (mp = pmap_avail; mp->size; mp++) {
1460		/*
1461		 * Check if this region holds all of the region
1462		 */
1463		mpend = mp->start + mp->size;
1464		if (base > mpend) {
1465			continue;
1466		}
1467		if (base <= mp->start) {
1468			if (end <= mp->start)
1469				break; /* region not present -??? */
1470
1471			if (end >= mpend) {
1472				/* covers whole region */
1473				/* shorten */
1474				for (i = mp - pmap_avail;
1475				    i < pmap_cnt_avail;
1476				    i++) {
1477					pmap_avail[i] = pmap_avail[i+1];
1478				}
1479				pmap_cnt_avail--;
1480				pmap_avail[pmap_cnt_avail].size = 0;
1481			} else {
1482				mp->start = end;
1483				mp->size = mpend - end;
1484			}
1485		} else {
1486			/* start after the beginning */
1487			if (end >= mpend) {
1488				/* just truncate */
1489				mp->size = base - mp->start;
1490			} else {
1491				/* split */
1492				for (i = pmap_cnt_avail;
1493				    i > (mp - pmap_avail);
1494				    i--) {
1495					pmap_avail[i] = pmap_avail[i - 1];
1496				}
1497				pmap_cnt_avail++;
1498				mp->size = base - mp->start;
1499				mp++;
1500				mp->start = end;
1501				mp->size = mpend - end;
1502			}
1503		}
1504	}
1505	for (mp = pmap_allocated; mp->size != 0; mp++) {
1506		if (base < mp->start) {
1507			if (end == mp->start) {
1508				mp->start = base;
1509				mp->size += end - base;
1510				break;
1511			}
1512			/* lengthen */
1513			for (i = pmap_cnt_allocated; i > (mp - pmap_allocated);
1514			    i--) {
1515				pmap_allocated[i] = pmap_allocated[i - 1];
1516			}
1517			pmap_cnt_allocated++;
1518			mp->start = base;
1519			mp->size = end - base;
1520			return;
1521		}
1522		if (base == (mp->start + mp->size)) {
1523			mp->size += end - base;
1524			return;
1525		}
1526	}
1527	if (mp->size == 0) {
1528		mp->start = base;
1529		mp->size  = end - base;
1530		pmap_cnt_allocated++;
1531	}
1532}
1533
1534void *
1535pmap_steal_avail(size_t size, int align)
1536{
1537	struct mem_region *mp;
1538	int start;
1539	int remsize;
1540
1541	for (mp = pmap_avail; mp->size; mp++) {
1542		if (mp->size > size) {
1543			start = (mp->start + (align -1)) & ~(align -1);
1544			remsize = mp->size - (start - mp->start);
1545			if (remsize >= 0) {
1546				pmap_remove_avail(start, start+size);
1547				return (void *)start;
1548			}
1549		}
1550	}
1551	panic ("unable to allocate region with size %x align %x",
1552	    size, align);
1553}
1554
1555/*
1556 * Similar to pmap_steal_avail, but operating on vm_physmem since
1557 * uvm_page_physload() has been called.
1558 */
1559vaddr_t
1560pmap_steal_memory(vsize_t size, vaddr_t *start, vaddr_t *end)
1561{
1562	int segno;
1563	u_int npg;
1564	vaddr_t va;
1565	paddr_t pa;
1566	struct vm_physseg *seg;
1567
1568	size = round_page(size);
1569	npg = atop(size);
1570
1571	for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) {
1572		if (seg->avail_end - seg->avail_start < npg)
1573			continue;
1574		/*
1575		 * We can only steal at an ``unused'' segment boundary,
1576		 * i.e. either at the start or at the end.
1577		 */
1578		if (seg->avail_start == seg->start ||
1579		    seg->avail_end == seg->end)
1580			break;
1581	}
1582	if (segno == vm_nphysseg)
1583		va = 0;
1584	else {
1585		if (seg->avail_start == seg->start) {
1586			pa = ptoa(seg->avail_start);
1587			seg->avail_start += npg;
1588			seg->start += npg;
1589		} else {
1590			pa = ptoa(seg->avail_end) - size;
1591			seg->avail_end -= npg;
1592			seg->end -= npg;
1593		}
1594		/*
1595		 * If all the segment has been consumed now, remove it.
1596		 * Note that the crash dump code still knows about it
1597		 * and will dump it correctly.
1598		 */
1599		if (seg->start == seg->end) {
1600			if (vm_nphysseg-- == 1)
1601				panic("pmap_steal_memory: out of memory");
1602			while (segno < vm_nphysseg) {
1603				seg[0] = seg[1]; /* struct copy */
1604				seg++;
1605				segno++;
1606			}
1607		}
1608
1609		va = (vaddr_t)pa;	/* 1:1 mapping */
1610		bzero((void *)va, size);
1611	}
1612
1613	if (start != NULL)
1614		*start = VM_MIN_KERNEL_ADDRESS;
1615	if (end != NULL)
1616		*end = VM_MAX_KERNEL_ADDRESS;
1617
1618	return (va);
1619}
1620
1621void *msgbuf_addr;
1622
1623/*
1624 * Initialize pmap setup.
1625 * ALL of the code which deals with avail needs rewritten as an actual
1626 * memory allocation.
1627 */
1628void
1629pmap_bootstrap(u_int kernelstart, u_int kernelend)
1630{
1631	struct mem_region *mp;
1632	int i, k;
1633	struct pmapvp *vp1;
1634	struct pmapvp *vp2;
1635
1636	ppc_check_procid();
1637
1638	/*
1639	 * Get memory.
1640	 */
1641	pmap_avail_setup();
1642
1643	/*
1644	 * Page align all regions.
1645	 * Non-page memory isn't very interesting to us.
1646	 * Also, sort the entries for ascending addresses.
1647	 */
1648	kernelstart = trunc_page(kernelstart);
1649	kernelend = round_page(kernelend);
1650	pmap_remove_avail(kernelstart, kernelend);
1651
1652	msgbuf_addr = pmap_steal_avail(MSGBUFSIZE,4);
1653
1654#ifdef DEBUG
1655	for (mp = pmap_avail; mp->size; mp++) {
1656		bzero((void *)mp->start, mp->size);
1657	}
1658#endif
1659
1660#define HTABENTS_32 1024
1661#define HTABENTS_64 2048
1662
1663	if (ppc_proc_is_64b) {
1664		pmap_ptab_cnt = HTABENTS_64;
1665		while (pmap_ptab_cnt * 2 < physmem)
1666			pmap_ptab_cnt <<= 1;
1667	} else {
1668		pmap_ptab_cnt = HTABENTS_32;
1669		while (HTABSIZE_32 < (ptoa(physmem) >> 7))
1670			pmap_ptab_cnt <<= 1;
1671	}
1672	/*
1673	 * allocate suitably aligned memory for HTAB
1674	 */
1675	if (ppc_proc_is_64b) {
1676		pmap_ptable64 = pmap_steal_avail(HTABMEMSZ_64, HTABMEMSZ_64);
1677		bzero((void *)pmap_ptable64, HTABMEMSZ_64);
1678		pmap_ptab_mask = pmap_ptab_cnt - 1;
1679	} else {
1680		pmap_ptable32 = pmap_steal_avail(HTABSIZE_32, HTABSIZE_32);
1681		bzero((void *)pmap_ptable32, HTABSIZE_32);
1682		pmap_ptab_mask = pmap_ptab_cnt - 1;
1683	}
1684
1685	/* allocate v->p mappings for pmap_kernel() */
1686	for (i = 0; i < VP_SR_SIZE; i++) {
1687		pmap_kernel()->pm_vp[i] = NULL;
1688	}
1689	vp1 = pmap_steal_avail(sizeof (struct pmapvp), 4);
1690	bzero (vp1, sizeof(struct pmapvp));
1691	pmap_kernel()->pm_vp[PPC_KERNEL_SR] = vp1;
1692	for (i = 0; i < VP_IDX1_SIZE; i++) {
1693		vp2 = vp1->vp[i] = pmap_steal_avail(sizeof (struct pmapvp), 4);
1694		bzero (vp2, sizeof(struct pmapvp));
1695		for (k = 0; k < VP_IDX2_SIZE; k++) {
1696			struct pte_desc *pted;
1697			pted = pmap_steal_avail(sizeof (struct pte_desc), 4);
1698			bzero (pted, sizeof (struct pte_desc));
1699			vp2->vp[k] = pted;
1700		}
1701	}
1702
1703	if (ppc_proc_is_64b) {
1704		vp1 = pmap_steal_avail(sizeof (struct pmapvp), 4);
1705		bzero (vp1, sizeof(struct pmapvp));
1706		pmap_kernel()->pm_vp[0] = vp1;
1707		for (i = 0; i < VP_IDX1_SIZE; i++) {
1708			vp2 = vp1->vp[i] =
1709			    pmap_steal_avail(sizeof (struct pmapvp), 4);
1710			bzero (vp2, sizeof(struct pmapvp));
1711			for (k = 0; k < VP_IDX2_SIZE; k++) {
1712				struct pte_desc *pted;
1713				pted = pmap_steal_avail(sizeof (struct pte_desc), 4);
1714				bzero (pted, sizeof (struct pte_desc));
1715				vp2->vp[k] = pted;
1716			}
1717		}
1718	}
1719
1720	zero_page = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
1721	ppc_kvm_stolen += PAGE_SIZE;
1722	copy_src_page = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
1723	ppc_kvm_stolen += PAGE_SIZE;
1724	copy_dst_page = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
1725	ppc_kvm_stolen += PAGE_SIZE;
1726	ppc_kvm_stolen += reserve_dumppages( (caddr_t)(VM_MIN_KERNEL_ADDRESS +
1727	    ppc_kvm_stolen));
1728
1729
1730	/*
1731	 * Initialize kernel pmap and hardware.
1732	 */
1733#if NPMAPS >= PPC_KERNEL_SEGMENT / 16
1734	usedsr[PPC_KERNEL_SEGMENT / 16 / (sizeof usedsr[0] * 8)]
1735		|= 1 << ((PPC_KERNEL_SEGMENT / 16) % (sizeof usedsr[0] * 8));
1736#endif
1737	for (i = 0; i < 16; i++) {
1738		pmap_kernel()->pm_sr[i] = (PPC_KERNEL_SEG0 + i) | SR_NOEXEC;
1739		ppc_mtsrin(PPC_KERNEL_SEG0 + i, i << ADDR_SR_SHIFT);
1740	}
1741
1742	if (ppc_proc_is_64b) {
1743		for(i = 0; i < 0x10000; i++)
1744			pmap_kenter_cache(ptoa(i), ptoa(i), VM_PROT_ALL,
1745			    PMAP_CACHE_WB);
1746		asm volatile ("sync; mtsdr1 %0; isync"
1747		    :: "r"((u_int)pmap_ptable64 | HTABSIZE_64));
1748	} else
1749		asm volatile ("sync; mtsdr1 %0; isync"
1750		    :: "r"((u_int)pmap_ptable32 | (pmap_ptab_mask >> 10)));
1751
1752	pmap_avail_fixup();
1753
1754
1755	tlbia();
1756
1757	pmap_avail_fixup();
1758	for (mp = pmap_avail; mp->size; mp++) {
1759		if (mp->start > 0x80000000)
1760			continue;
1761		if (mp->start + mp->size > 0x80000000)
1762			mp->size = 0x80000000 - mp->start;
1763		uvm_page_physload(atop(mp->start), atop(mp->start+mp->size),
1764		    atop(mp->start), atop(mp->start+mp->size), 0);
1765	}
1766}
1767
1768/*
1769 * activate a pmap entry
1770 * NOOP on powerpc, all PTE entries exist in the same hash table.
1771 * Segment registers are filled on exit to user mode.
1772 */
1773void
1774pmap_activate(struct proc *p)
1775{
1776}
1777
1778/*
1779 * deactivate a pmap entry
1780 * NOOP on powerpc
1781 */
1782void
1783pmap_deactivate(struct proc *p)
1784{
1785}
1786
1787/*
1788 * Get the physical page address for the given pmap/virtual address.
1789 */
1790boolean_t
1791pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pa)
1792{
1793	struct pte_desc *pted;
1794
1795	pted = pmap_vp_lookup(pm, va);
1796	if (pted == NULL || !PTED_VALID(pted)) {
1797		if (pm == pmap_kernel() && va < 0x80000000) {
1798			/* XXX - this is not true without BATs */
1799			/* if in kernel, va==pa for 0-0x80000000 */
1800			*pa = va;
1801			return TRUE;
1802		}
1803		return FALSE;
1804	}
1805	if (ppc_proc_is_64b)
1806		*pa = (pted->p.pted_pte64.pte_lo & PTE_RPGN_64) |
1807		    (va & ~PTE_RPGN_64);
1808	else
1809		*pa = (pted->p.pted_pte32.pte_lo & PTE_RPGN_32) |
1810		    (va & ~PTE_RPGN_32);
1811	return TRUE;
1812}
1813
1814u_int32_t
1815pmap_setusr(pmap_t pm, vaddr_t va)
1816{
1817	u_int32_t sr;
1818	u_int32_t oldsr;
1819
1820	sr = pm->pm_sr[(u_int)va >> ADDR_SR_SHIFT];
1821
1822	/* user address range lock?? */
1823	asm volatile ("mfsr %0,%1"
1824	    : "=r" (oldsr): "n"(PPC_USER_SR));
1825	asm volatile ("isync; mtsr %0,%1; isync"
1826	    :: "n"(PPC_USER_SR), "r"(sr));
1827	return oldsr;
1828}
1829
1830void
1831pmap_popusr(u_int32_t sr)
1832{
1833	asm volatile ("isync; mtsr %0,%1; isync"
1834	    :: "n"(PPC_USER_SR), "r"(sr));
1835}
1836
1837int
1838copyin(const void *udaddr, void *kaddr, size_t len)
1839{
1840	void *p;
1841	size_t l;
1842	u_int32_t oldsr;
1843	faultbuf env;
1844	void *oldh = curpcb->pcb_onfault;
1845
1846	while (len > 0) {
1847		p = PPC_USER_ADDR + ((u_int)udaddr & ~PPC_SEGMENT_MASK);
1848		l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p;
1849		if (l > len)
1850			l = len;
1851		oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)udaddr);
1852		if (setfault(&env)) {
1853			pmap_popusr(oldsr);
1854			curpcb->pcb_onfault = oldh;
1855			return EFAULT;
1856		}
1857		bcopy(p, kaddr, l);
1858		pmap_popusr(oldsr);
1859		udaddr += l;
1860		kaddr += l;
1861		len -= l;
1862	}
1863	curpcb->pcb_onfault = oldh;
1864	return 0;
1865}
1866
1867int
1868copyout(const void *kaddr, void *udaddr, size_t len)
1869{
1870	void *p;
1871	size_t l;
1872	u_int32_t oldsr;
1873	faultbuf env;
1874	void *oldh = curpcb->pcb_onfault;
1875
1876	while (len > 0) {
1877		p = PPC_USER_ADDR + ((u_int)udaddr & ~PPC_SEGMENT_MASK);
1878		l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p;
1879		if (l > len)
1880			l = len;
1881		oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)udaddr);
1882		if (setfault(&env)) {
1883			pmap_popusr(oldsr);
1884			curpcb->pcb_onfault = oldh;
1885			return EFAULT;
1886		}
1887
1888		bcopy(kaddr, p, l);
1889		pmap_popusr(oldsr);
1890		udaddr += l;
1891		kaddr += l;
1892		len -= l;
1893	}
1894	curpcb->pcb_onfault = oldh;
1895	return 0;
1896}
1897
1898int
1899copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
1900{
1901	const u_char *uaddr = udaddr;
1902	u_char *kp    = kaddr;
1903	u_char *up;
1904	u_char c;
1905	void   *p;
1906	size_t	 l;
1907	u_int32_t oldsr;
1908	int cnt = 0;
1909	faultbuf env;
1910	void *oldh = curpcb->pcb_onfault;
1911
1912	while (len > 0) {
1913		p = PPC_USER_ADDR + ((u_int)uaddr & ~PPC_SEGMENT_MASK);
1914		l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p;
1915		up = p;
1916		if (l > len)
1917			l = len;
1918		len -= l;
1919		oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)uaddr);
1920		if (setfault(&env)) {
1921			if (done != NULL)
1922				*done =  cnt;
1923
1924			curpcb->pcb_onfault = oldh;
1925			pmap_popusr(oldsr);
1926			return EFAULT;
1927		}
1928		while (l > 0) {
1929			c = *up;
1930			*kp = c;
1931			if (c == 0) {
1932				if (done != NULL)
1933					*done = cnt + 1;
1934
1935				curpcb->pcb_onfault = oldh;
1936				pmap_popusr(oldsr);
1937				return 0;
1938			}
1939			up++;
1940			kp++;
1941			l--;
1942			cnt++;
1943			uaddr++;
1944		}
1945		pmap_popusr(oldsr);
1946	}
1947	curpcb->pcb_onfault = oldh;
1948	if (done != NULL)
1949		*done = cnt;
1950
1951	return ENAMETOOLONG;
1952}
1953
1954int
1955copyoutstr(const void *kaddr, void *udaddr, size_t len, size_t *done)
1956{
1957	u_char *uaddr = (void *)udaddr;
1958	const u_char *kp    = kaddr;
1959	u_char *up;
1960	u_char c;
1961	void   *p;
1962	size_t	 l;
1963	u_int32_t oldsr;
1964	int cnt = 0;
1965	faultbuf env;
1966	void *oldh = curpcb->pcb_onfault;
1967
1968	while (len > 0) {
1969		p = PPC_USER_ADDR + ((u_int)uaddr & ~PPC_SEGMENT_MASK);
1970		l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p;
1971		up = p;
1972		if (l > len)
1973			l = len;
1974		len -= l;
1975		oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)uaddr);
1976		if (setfault(&env)) {
1977			if (done != NULL)
1978				*done =  cnt;
1979
1980			curpcb->pcb_onfault = oldh;
1981			pmap_popusr(oldsr);
1982			return EFAULT;
1983		}
1984		while (l > 0) {
1985			c = *kp;
1986			*up = c;
1987			if (c == 0) {
1988				if (done != NULL)
1989					*done = cnt + 1;
1990
1991				curpcb->pcb_onfault = oldh;
1992				pmap_popusr(oldsr);
1993				return 0;
1994			}
1995			up++;
1996			kp++;
1997			l--;
1998			cnt++;
1999			uaddr++;
2000		}
2001		pmap_popusr(oldsr);
2002	}
2003	curpcb->pcb_onfault = oldh;
2004	if (done != NULL)
2005		*done = cnt;
2006
2007	return ENAMETOOLONG;
2008}
2009
2010/*
2011 * sync instruction cache for user virtual address.
2012 * The address WAS JUST MAPPED, so we have a VALID USERSPACE mapping
2013 */
2014void
2015pmap_syncicache_user_virt(pmap_t pm, vaddr_t va)
2016{
2017	vaddr_t start;
2018	int oldsr;
2019
2020	if (pm != pmap_kernel()) {
2021		start = ((u_int)PPC_USER_ADDR + ((u_int)va &
2022		    ~PPC_SEGMENT_MASK));
2023		/* will only ever be page size, will not cross segments */
2024
2025		/* USER SEGMENT LOCK - MPXXX */
2026		oldsr = pmap_setusr(pm, va);
2027	} else {
2028		start = va; /* flush mapped page */
2029	}
2030
2031	syncicache((void *)start, PAGE_SIZE);
2032
2033	if (pm != pmap_kernel()) {
2034		pmap_popusr(oldsr);
2035		/* USER SEGMENT UNLOCK -MPXXX */
2036	}
2037}
2038
2039void
2040pmap_page_ro64(pmap_t pm, vaddr_t va, vm_prot_t prot)
2041{
2042	struct pte_64 *ptp64;
2043	struct pte_desc *pted;
2044	struct vm_page *pg;
2045	int sr, idx;
2046
2047	pted = pmap_vp_lookup(pm, va);
2048	if (pted == NULL || !PTED_VALID(pted))
2049		return;
2050
2051	pg = PHYS_TO_VM_PAGE(pted->p.pted_pte64.pte_lo & PTE_RPGN_64);
2052	if (pg->pg_flags & PG_PMAP_EXE) {
2053		if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) == VM_PROT_WRITE) {
2054			atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE);
2055		} else {
2056			pmap_syncicache_user_virt(pm, va);
2057		}
2058	}
2059
2060	pted->p.pted_pte64.pte_lo &= ~PTE_PP_64;
2061	pted->p.pted_pte64.pte_lo |= PTE_RO_64;
2062
2063	if ((prot & VM_PROT_EXECUTE) == 0)
2064		pted->p.pted_pte64.pte_lo |= PTE_N_64;
2065
2066	sr = ptesr(pm->pm_sr, va);
2067	idx = pteidx(sr, va);
2068
2069	/* determine which pteg mapping is present in */
2070	ptp64 = pmap_ptable64 +
2071	    (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8;
2072	ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */
2073
2074	/*
2075	 * We now have the pointer to where it will be, if it is
2076	 * currently mapped. If the mapping was thrown away in
2077	 * exchange for another page mapping, then this page is
2078	 * not currently in the HASH.
2079	 */
2080	if ((pted->p.pted_pte64.pte_hi | (PTED_HID(pted) ? PTE_HID_64 : 0))
2081	    == ptp64->pte_hi) {
2082		ptp64->pte_hi &= ~PTE_VALID_64;
2083		__asm__ volatile ("sync");
2084		tlbie(va);
2085		tlbsync();
2086		if (PTED_MANAGED(pted)) { /* XXX */
2087			pmap_attr_save(ptp64->pte_lo & PTE_RPGN_64,
2088			    ptp64->pte_lo & (PTE_REF_64|PTE_CHG_64));
2089		}
2090		ptp64->pte_lo &= ~PTE_CHG_64;
2091		ptp64->pte_lo &= ~PTE_PP_64;
2092		ptp64->pte_lo |= PTE_RO_64;
2093		__asm__ volatile ("sync");
2094		ptp64->pte_hi |= PTE_VALID_64;
2095	}
2096}
2097
2098void
2099pmap_page_ro32(pmap_t pm, vaddr_t va, vm_prot_t prot)
2100{
2101	struct pte_32 *ptp32;
2102	struct pte_desc *pted;
2103	struct vm_page *pg = NULL;
2104	int sr, idx;
2105
2106	pted = pmap_vp_lookup(pm, va);
2107	if (pted == NULL || !PTED_VALID(pted))
2108		return;
2109
2110	pg = PHYS_TO_VM_PAGE(pted->p.pted_pte32.pte_lo & PTE_RPGN_32);
2111	if (pg->pg_flags & PG_PMAP_EXE) {
2112		if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) == VM_PROT_WRITE) {
2113			atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE);
2114		} else {
2115			pmap_syncicache_user_virt(pm, va);
2116		}
2117	}
2118
2119	pted->p.pted_pte32.pte_lo &= ~PTE_PP_32;
2120	pted->p.pted_pte32.pte_lo |= PTE_RO_32;
2121
2122	sr = ptesr(pm->pm_sr, va);
2123	idx = pteidx(sr, va);
2124
2125	/* determine which pteg mapping is present in */
2126	ptp32 = pmap_ptable32 +
2127	    (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8;
2128	ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */
2129
2130	/*
2131	 * We now have the pointer to where it will be, if it is
2132	 * currently mapped. If the mapping was thrown away in
2133	 * exchange for another page mapping, then this page is
2134	 * not currently in the HASH.
2135	 */
2136	if ((pted->p.pted_pte32.pte_hi | (PTED_HID(pted) ? PTE_HID_32 : 0))
2137	    == ptp32->pte_hi) {
2138		ptp32->pte_hi &= ~PTE_VALID_32;
2139		__asm__ volatile ("sync");
2140		tlbie(va);
2141		tlbsync();
2142		if (PTED_MANAGED(pted)) { /* XXX */
2143			pmap_attr_save(ptp32->pte_lo & PTE_RPGN_32,
2144			    ptp32->pte_lo & (PTE_REF_32|PTE_CHG_32));
2145		}
2146		ptp32->pte_lo &= ~PTE_CHG_32;
2147		ptp32->pte_lo &= ~PTE_PP_32;
2148		ptp32->pte_lo |= PTE_RO_32;
2149		__asm__ volatile ("sync");
2150		ptp32->pte_hi |= PTE_VALID_32;
2151	}
2152}
2153
2154/*
2155 * Lower the protection on the specified physical page.
2156 *
2157 * There are only two cases, either the protection is going to 0,
2158 * or it is going to read-only.
2159 */
2160void
2161pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
2162{
2163	int s;
2164	struct pte_desc *pted;
2165
2166	/* need to lock for this pv */
2167	s = splvm();
2168
2169	if (prot == VM_PROT_NONE) {
2170		while (!LIST_EMPTY(&(pg->mdpage.pv_list))) {
2171			pted = LIST_FIRST(&(pg->mdpage.pv_list));
2172			pmap_remove_pg(pted->pted_pmap, pted->pted_va);
2173		}
2174		/* page is being reclaimed, sync icache next use */
2175		atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE);
2176		splx(s);
2177		return;
2178	}
2179
2180	LIST_FOREACH(pted, &(pg->mdpage.pv_list), pted_pv_list) {
2181		if (ppc_proc_is_64b)
2182			pmap_page_ro64(pted->pted_pmap, pted->pted_va, prot);
2183		else
2184			pmap_page_ro32(pted->pted_pmap, pted->pted_va, prot);
2185	}
2186	splx(s);
2187}
2188
2189void
2190pmap_protect(pmap_t pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
2191{
2192	int s;
2193	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2194		s = splvm();
2195		if (ppc_proc_is_64b) {
2196			while (sva < eva) {
2197				pmap_page_ro64(pm, sva, prot);
2198				sva += PAGE_SIZE;
2199			}
2200		} else {
2201			while (sva < eva) {
2202				pmap_page_ro32(pm, sva, prot);
2203				sva += PAGE_SIZE;
2204			}
2205		}
2206		splx(s);
2207		return;
2208	}
2209	pmap_remove(pm, sva, eva);
2210}
2211
2212/*
2213 * Restrict given range to physical memory
2214 */
2215void
2216pmap_real_memory(paddr_t *start, vsize_t *size)
2217{
2218	struct mem_region *mp;
2219
2220	for (mp = pmap_mem; mp->size; mp++) {
2221		if (((*start + *size) > mp->start)
2222			&& (*start < (mp->start + mp->size)))
2223		{
2224			if (*start < mp->start) {
2225				*size -= mp->start - *start;
2226				*start = mp->start;
2227			}
2228			if ((*start + *size) > (mp->start + mp->size))
2229				*size = mp->start + mp->size - *start;
2230			return;
2231		}
2232	}
2233	*size = 0;
2234}
2235
2236void
2237pmap_init()
2238{
2239	pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmap", NULL);
2240	pool_setlowat(&pmap_pmap_pool, 2);
2241	pool_init(&pmap_vp_pool, sizeof(struct pmapvp), 0, 0, 0, "vp", NULL);
2242	pool_setlowat(&pmap_vp_pool, 10);
2243	pool_init(&pmap_pted_pool, sizeof(struct pte_desc), 0, 0, 0, "pted",
2244	    NULL);
2245	pool_setlowat(&pmap_pted_pool, 20);
2246
2247	pmap_initialized = 1;
2248}
2249
2250void
2251pmap_proc_iflush(struct proc *p, vaddr_t addr, vsize_t len)
2252{
2253	paddr_t pa;
2254	vsize_t clen;
2255
2256	while (len > 0) {
2257		/* add one to always round up to the next page */
2258		clen = round_page(addr + 1) - addr;
2259		if (clen > len)
2260			clen = len;
2261
2262		if (pmap_extract(p->p_vmspace->vm_map.pmap, addr, &pa)) {
2263			syncicache((void *)pa, clen);
2264		}
2265
2266		len -= clen;
2267		addr += clen;
2268	}
2269}
2270
2271/*
2272 * There are two routines, pte_spill_r and pte_spill_v
2273 * the _r version only handles kernel faults which are not user
2274 * accesses. The _v version handles all user faults and kernel copyin/copyout
2275 * "user" accesses.
2276 */
2277int
2278pte_spill_r(u_int32_t va, u_int32_t msr, u_int32_t dsisr, int exec_fault)
2279{
2280	pmap_t pm;
2281	struct pte_desc *pted;
2282	struct pte_desc pted_store;
2283
2284	/* lookup is done physical to prevent faults */
2285
2286	/*
2287	 * This function only handles kernel faults, not supervisor copyins.
2288	 */
2289	if (msr & PSL_PR)
2290		return 0;
2291
2292	/* if copyin, throw to full excption handler */
2293	if (VP_SR(va) == PPC_USER_SR)
2294		return 0;
2295
2296	pm = pmap_kernel();
2297
2298
2299	if (va < physmaxaddr) {
2300		u_int32_t aligned_va;
2301		pted =  &pted_store;
2302		/* 0 - physmaxaddr mapped 1-1 */
2303		/* XXX - no WRX control */
2304
2305		aligned_va = trunc_page(va);
2306		if (ppc_proc_is_64b) {
2307			pmap_fill_pte64(pm, aligned_va, aligned_va,
2308			    pted, VM_PROT_READ | VM_PROT_WRITE |
2309			    VM_PROT_EXECUTE, 0, PMAP_CACHE_WB);
2310			pte_insert64(pted);
2311			return 1;
2312		} else {
2313			pmap_fill_pte32(pm, aligned_va, aligned_va,
2314			    &pted_store, VM_PROT_READ | VM_PROT_WRITE |
2315			    VM_PROT_EXECUTE, 0, PMAP_CACHE_WB);
2316			pte_insert32(pted);
2317			return 1;
2318		}
2319		/* NOTREACHED */
2320	}
2321
2322	pted = pmap_vp_lookup(pm, va);
2323	if (pted == NULL) {
2324		return 0;
2325	}
2326
2327	/* if the current mapping is RO and the access was a write
2328	 * we return 0
2329	 */
2330	if (!PTED_VALID(pted)) {
2331		return 0;
2332	}
2333
2334	if (ppc_proc_is_64b) {
2335		/* check write fault and we have a readonly mapping */
2336		if ((dsisr & (1 << (31-6))) &&
2337		    (pted->p.pted_pte64.pte_lo & 0x1))
2338			return 0;
2339		if ((exec_fault != 0)
2340		    && ((pted->pted_va & PTED_VA_EXEC_M) == 0)) {
2341			/* attempted to execute non-executable page */
2342			return 0;
2343		}
2344		pte_insert64(pted);
2345	} else {
2346		/* check write fault and we have a readonly mapping */
2347		if ((dsisr & (1 << (31-6))) &&
2348		    (pted->p.pted_pte32.pte_lo & 0x1))
2349			return 0;
2350		if ((exec_fault != 0)
2351		    && ((pted->pted_va & PTED_VA_EXEC_M) == 0)) {
2352			/* attempted to execute non-executable page */
2353			return 0;
2354		}
2355		pte_insert32(pted);
2356	}
2357
2358	return 1;
2359}
2360
2361int
2362pte_spill_v(pmap_t pm, u_int32_t va, u_int32_t dsisr, int exec_fault)
2363{
2364	struct pte_desc *pted;
2365
2366	pted = pmap_vp_lookup(pm, va);
2367	if (pted == NULL) {
2368		return 0;
2369	}
2370
2371	/*
2372	 * if the current mapping is RO and the access was a write
2373	 * we return 0
2374	 */
2375	if (!PTED_VALID(pted)) {
2376		return 0;
2377	}
2378	if (ppc_proc_is_64b) {
2379		/* check write fault and we have a readonly mapping */
2380		if ((dsisr & (1 << (31-6))) &&
2381		    (pted->p.pted_pte64.pte_lo & 0x1))
2382			return 0;
2383	} else {
2384		/* check write fault and we have a readonly mapping */
2385		if ((dsisr & (1 << (31-6))) &&
2386		    (pted->p.pted_pte32.pte_lo & 0x1))
2387			return 0;
2388	}
2389	if ((exec_fault != 0)
2390	    && ((pted->pted_va & PTED_VA_EXEC_M) == 0)) {
2391		/* attempted to execute non-executable page */
2392		return 0;
2393	}
2394	if (ppc_proc_is_64b)
2395		pte_insert64(pted);
2396	else
2397		pte_insert32(pted);
2398	return 1;
2399}
2400
2401
2402/*
2403 * should pte_insert code avoid wired mappings?
2404 * is the stack safe?
2405 * is the pted safe? (physical)
2406 * -ugh
2407 */
2408void
2409pte_insert64(struct pte_desc *pted)
2410{
2411	int off;
2412	int secondary;
2413	struct pte_64 *ptp64;
2414	int sr, idx;
2415	int i, s;
2416
2417
2418	sr = ptesr(pted->pted_pmap->pm_sr, pted->pted_va);
2419	idx = pteidx(sr, pted->pted_va);
2420
2421	ptp64 = pmap_ptable64 +
2422	    (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8;
2423	ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */
2424	if ((pted->p.pted_pte64.pte_hi |
2425	    (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi)
2426		pte_zap(ptp64,pted);
2427
2428	pted->pted_va &= ~(PTED_VA_HID_M|PTED_VA_PTEGIDX_M);
2429
2430	/*
2431	 * instead of starting at the beginning of each pteg,
2432	 * the code should pick a random location with in the primary
2433	 * then search all of the entries, then if not yet found,
2434	 * do the same for the secondary.
2435	 * this would reduce the frontloading of the pteg.
2436	 */
2437	/* first just try fill of primary hash */
2438	ptp64 = pmap_ptable64 + (idx) * 8;
2439	for (i = 0; i < 8; i++) {
2440		if (ptp64[i].pte_hi & PTE_VALID_64)
2441			continue;
2442		s = ppc_intr_disable();
2443		if (pmap_hash_lock_try(i) == 0) {
2444			ppc_intr_enable(s);
2445			continue;
2446		}
2447
2448		/* not valid, just load */
2449		pted->pted_va |= i;
2450		ptp64[i].pte_hi =
2451		    pted->p.pted_pte64.pte_hi & ~PTE_VALID_64;
2452		ptp64[i].pte_lo = pted->p.pted_pte64.pte_lo;
2453		__asm__ volatile ("sync");
2454		ptp64[i].pte_hi |= PTE_VALID_64;
2455		__asm volatile ("sync");
2456
2457		pmap_hash_unlock(i);
2458		ppc_intr_enable(s);
2459		return;
2460	}
2461	/* try fill of secondary hash */
2462	ptp64 = pmap_ptable64 + (idx ^ pmap_ptab_mask) * 8;
2463	for (i = 0; i < 8; i++) {
2464		if (ptp64[i].pte_hi & PTE_VALID_64)
2465			continue;
2466		s = ppc_intr_disable();
2467		if (pmap_hash_lock_try(i) == 0) {
2468			ppc_intr_enable(s);
2469			continue;
2470		}
2471
2472		pted->pted_va |= (i | PTED_VA_HID_M);
2473		ptp64[i].pte_hi =
2474		    (pted->p.pted_pte64.pte_hi | PTE_HID_64) & ~PTE_VALID_64;
2475		ptp64[i].pte_lo = pted->p.pted_pte64.pte_lo;
2476		__asm__ volatile ("sync");
2477		ptp64[i].pte_hi |= PTE_VALID_64;
2478		__asm volatile ("sync");
2479
2480		pmap_hash_unlock(i);
2481		ppc_intr_enable(s);
2482		return;
2483	}
2484
2485	/* need decent replacement algorithm */
2486busy:
2487	__asm__ volatile ("mftb %0" : "=r"(off));
2488	secondary = off & 8;
2489
2490	s = ppc_intr_disable();
2491	if (pmap_hash_lock_try(off & 7) == 0) {
2492		ppc_intr_enable(s);
2493		goto busy;
2494	}
2495
2496	pted->pted_va |= off & (PTED_VA_PTEGIDX_M|PTED_VA_HID_M);
2497
2498	idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0));
2499
2500	ptp64 = pmap_ptable64 + (idx * 8);
2501	ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */
2502	if (ptp64->pte_hi & PTE_VALID_64) {
2503		vaddr_t va;
2504		ptp64->pte_hi &= ~PTE_VALID_64;
2505		__asm volatile ("sync");
2506
2507		/* Bits 9-19 */
2508		idx = (idx ^ ((ptp64->pte_hi & PTE_HID_64) ?
2509		    pmap_ptab_mask : 0));
2510		va = (ptp64->pte_hi >> PTE_VSID_SHIFT_64) ^ idx;
2511		va <<= ADDR_PIDX_SHIFT;
2512		/* Bits 4-8 */
2513		va |= (ptp64->pte_hi & PTE_API_64) << ADDR_API_SHIFT_32;
2514		/* Bits 0-3 */
2515		va |= (ptp64->pte_hi >> PTE_VSID_SHIFT_64)
2516		    << ADDR_SR_SHIFT;
2517		tlbie(va);
2518
2519		tlbsync();
2520		pmap_attr_save(ptp64->pte_lo & PTE_RPGN_64,
2521		    ptp64->pte_lo & (PTE_REF_64|PTE_CHG_64));
2522	}
2523
2524	if (secondary)
2525		ptp64->pte_hi =
2526		    (pted->p.pted_pte64.pte_hi | PTE_HID_64) &
2527		    ~PTE_VALID_64;
2528	 else
2529		ptp64->pte_hi = pted->p.pted_pte64.pte_hi &
2530		    ~PTE_VALID_64;
2531
2532	ptp64->pte_lo = pted->p.pted_pte64.pte_lo;
2533	__asm__ volatile ("sync");
2534	ptp64->pte_hi |= PTE_VALID_64;
2535
2536	pmap_hash_unlock(off & 7);
2537	ppc_intr_enable(s);
2538}
2539
2540void
2541pte_insert32(struct pte_desc *pted)
2542{
2543	int off;
2544	int secondary;
2545	struct pte_32 *ptp32;
2546	int sr, idx;
2547	int i, s;
2548
2549	sr = ptesr(pted->pted_pmap->pm_sr, pted->pted_va);
2550	idx = pteidx(sr, pted->pted_va);
2551
2552	/* determine if ptp is already mapped */
2553	ptp32 = pmap_ptable32 +
2554	    (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8;
2555	ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */
2556	if ((pted->p.pted_pte32.pte_hi |
2557	    (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi)
2558		pte_zap(ptp32,pted);
2559
2560	pted->pted_va &= ~(PTED_VA_HID_M|PTED_VA_PTEGIDX_M);
2561
2562	/*
2563	 * instead of starting at the beginning of each pteg,
2564	 * the code should pick a random location with in the primary
2565	 * then search all of the entries, then if not yet found,
2566	 * do the same for the secondary.
2567	 * this would reduce the frontloading of the pteg.
2568	 */
2569
2570	/* first just try fill of primary hash */
2571	ptp32 = pmap_ptable32 + (idx) * 8;
2572	for (i = 0; i < 8; i++) {
2573		if (ptp32[i].pte_hi & PTE_VALID_32)
2574			continue;
2575		s = ppc_intr_disable();
2576		if (pmap_hash_lock_try(i) == 0) {
2577			ppc_intr_enable(s);
2578			continue;
2579		}
2580
2581		/* not valid, just load */
2582		pted->pted_va |= i;
2583		ptp32[i].pte_hi = pted->p.pted_pte32.pte_hi & ~PTE_VALID_32;
2584		ptp32[i].pte_lo = pted->p.pted_pte32.pte_lo;
2585		__asm__ volatile ("sync");
2586		ptp32[i].pte_hi |= PTE_VALID_32;
2587		__asm volatile ("sync");
2588
2589		pmap_hash_unlock(i);
2590		ppc_intr_enable(s);
2591		return;
2592	}
2593	/* try fill of secondary hash */
2594	ptp32 = pmap_ptable32 + (idx ^ pmap_ptab_mask) * 8;
2595	for (i = 0; i < 8; i++) {
2596		if (ptp32[i].pte_hi & PTE_VALID_32)
2597			continue;
2598		s = ppc_intr_disable();
2599		if (pmap_hash_lock_try(i) == 0) {
2600			ppc_intr_enable(s);
2601			continue;
2602		}
2603
2604		pted->pted_va |= (i | PTED_VA_HID_M);
2605		ptp32[i].pte_hi =
2606		    (pted->p.pted_pte32.pte_hi | PTE_HID_32) & ~PTE_VALID_32;
2607		ptp32[i].pte_lo = pted->p.pted_pte32.pte_lo;
2608		__asm__ volatile ("sync");
2609		ptp32[i].pte_hi |= PTE_VALID_32;
2610		__asm volatile ("sync");
2611
2612		pmap_hash_unlock(i);
2613		ppc_intr_enable(s);
2614		return;
2615	}
2616
2617	/* need decent replacement algorithm */
2618busy:
2619	__asm__ volatile ("mftb %0" : "=r"(off));
2620	secondary = off & 8;
2621	s = ppc_intr_disable();
2622	if (pmap_hash_lock_try(off & 7) == 0) {
2623		ppc_intr_enable(s);
2624		goto busy;
2625	}
2626
2627	pted->pted_va |= off & (PTED_VA_PTEGIDX_M|PTED_VA_HID_M);
2628
2629	idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0));
2630
2631	ptp32 = pmap_ptable32 + (idx * 8);
2632	ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */
2633	if (ptp32->pte_hi & PTE_VALID_32) {
2634		vaddr_t va;
2635		ptp32->pte_hi &= ~PTE_VALID_32;
2636		__asm volatile ("sync");
2637
2638		va = ((ptp32->pte_hi & PTE_API_32) << ADDR_API_SHIFT_32) |
2639		     ((((ptp32->pte_hi >> PTE_VSID_SHIFT_32) & SR_VSID)
2640			^(idx ^ ((ptp32->pte_hi & PTE_HID_32) ? 0x3ff : 0)))
2641			    & 0x3ff) << PAGE_SHIFT;
2642		tlbie(va);
2643
2644		tlbsync();
2645		pmap_attr_save(ptp32->pte_lo & PTE_RPGN_32,
2646		    ptp32->pte_lo & (PTE_REF_32|PTE_CHG_32));
2647	}
2648	if (secondary)
2649		ptp32->pte_hi =
2650		    (pted->p.pted_pte32.pte_hi | PTE_HID_32) & ~PTE_VALID_32;
2651	else
2652		ptp32->pte_hi = pted->p.pted_pte32.pte_hi & ~PTE_VALID_32;
2653	ptp32->pte_lo = pted->p.pted_pte32.pte_lo;
2654	__asm__ volatile ("sync");
2655	ptp32->pte_hi |= PTE_VALID_32;
2656
2657	pmap_hash_unlock(off & 7);
2658	ppc_intr_enable(s);
2659}
2660
2661#ifdef DEBUG_PMAP
2662void
2663print_pteg(pmap_t pm, vaddr_t va)
2664{
2665	int sr, idx;
2666	struct pte *ptp;
2667
2668	sr = ptesr(pm->pm_sr, va);
2669	idx = pteidx(sr,  va);
2670
2671	ptp = pmap_ptable + idx  * 8;
2672	db_printf("va %x, sr %x, idx %x\n", va, sr, idx);
2673
2674	db_printf("%08x %08x %08x %08x  %08x %08x %08x %08x\n",
2675	    ptp[0].pte_hi, ptp[1].pte_hi, ptp[2].pte_hi, ptp[3].pte_hi,
2676	    ptp[4].pte_hi, ptp[5].pte_hi, ptp[6].pte_hi, ptp[7].pte_hi);
2677	db_printf("%08x %08x %08x %08x  %08x %08x %08x %08x\n",
2678	    ptp[0].pte_lo, ptp[1].pte_lo, ptp[2].pte_lo, ptp[3].pte_lo,
2679	    ptp[4].pte_lo, ptp[5].pte_lo, ptp[6].pte_lo, ptp[7].pte_lo);
2680	ptp = pmap_ptable + (idx ^ pmap_ptab_mask) * 8;
2681	db_printf("%08x %08x %08x %08x  %08x %08x %08x %08x\n",
2682	    ptp[0].pte_hi, ptp[1].pte_hi, ptp[2].pte_hi, ptp[3].pte_hi,
2683	    ptp[4].pte_hi, ptp[5].pte_hi, ptp[6].pte_hi, ptp[7].pte_hi);
2684	db_printf("%08x %08x %08x %08x  %08x %08x %08x %08x\n",
2685	    ptp[0].pte_lo, ptp[1].pte_lo, ptp[2].pte_lo, ptp[3].pte_lo,
2686	    ptp[4].pte_lo, ptp[5].pte_lo, ptp[6].pte_lo, ptp[7].pte_lo);
2687}
2688
2689
2690/* debugger assist function */
2691int pmap_prtrans(u_int pid, vaddr_t va);
2692
2693void
2694pmap_print_pted(struct pte_desc *pted, int(*print)(const char *, ...))
2695{
2696	vaddr_t va;
2697	va = pted->pted_va & ~PAGE_MASK;
2698	print("\n pted %x", pted);
2699	if (PTED_VALID(pted)) {
2700		print(" va %x:", pted->pted_va & ~PAGE_MASK);
2701		print(" HID %d", PTED_HID(pted) ? 1: 0);
2702		print(" PTEGIDX %x", PTED_PTEGIDX(pted));
2703		print(" MANAGED %d", PTED_MANAGED(pted) ? 1: 0);
2704		print(" WIRED %d\n", PTED_WIRED(pted) ? 1: 0);
2705		if (ppc_proc_is_64b) {
2706			print("ptehi %x ptelo %x ptp %x Aptp %x\n",
2707			    pted->p.pted_pte64.pte_hi,
2708			    pted->p.pted_pte64.pte_lo,
2709			    pmap_ptable +
2710				8*pteidx(ptesr(pted->pted_pmap->pm_sr, va), va),
2711			    pmap_ptable +
2712				8*(pteidx(ptesr(pted->pted_pmap->pm_sr, va), va)
2713				    ^ pmap_ptab_mask)
2714			    );
2715		} else {
2716			print("ptehi %x ptelo %x ptp %x Aptp %x\n",
2717			    pted->p.pted_pte32.pte_hi,
2718			    pted->p.pted_pte32.pte_lo,
2719			    pmap_ptable +
2720				8*pteidx(ptesr(pted->pted_pmap->pm_sr, va), va),
2721			    pmap_ptable +
2722				8*(pteidx(ptesr(pted->pted_pmap->pm_sr, va), va)
2723				    ^ pmap_ptab_mask)
2724			    );
2725		}
2726	}
2727}
2728
2729int pmap_user_read(int size, vaddr_t va);
2730int
2731pmap_user_read(int size, vaddr_t va)
2732{
2733	unsigned char  read1;
2734	unsigned short read2;
2735	unsigned int   read4;
2736	int err;
2737
2738	if (size == 1) {
2739		err = copyin((void *)va, &read1, 1);
2740		if (err == 0) {
2741			db_printf("byte read %x\n", read1);
2742		}
2743	} else if (size == 2) {
2744		err = copyin((void *)va, &read2, 2);
2745		if (err == 0) {
2746			db_printf("short read %x\n", read2);
2747		}
2748	} else if (size == 4) {
2749		err = copyin((void *)va, &read4, 4);
2750		if (err == 0) {
2751			db_printf("int read %x\n", read4);
2752		}
2753	} else {
2754		return 1;
2755	}
2756
2757
2758	return 0;
2759}
2760
2761int pmap_dump_pmap(u_int pid);
2762int
2763pmap_dump_pmap(u_int pid)
2764{
2765	pmap_t pm;
2766	struct proc *p;
2767	if (pid == 0) {
2768		pm = pmap_kernel();
2769	} else {
2770		p = pfind(pid);
2771
2772		if (p == NULL) {
2773			db_printf("invalid pid %d", pid);
2774			return 1;
2775		}
2776		pm = p->p_vmspace->vm_map.pmap;
2777	}
2778	printf("pmap %x:\n", pm);
2779	printf("segid %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
2780	    pm->pm_sr[0], pm->pm_sr[1], pm->pm_sr[2], pm->pm_sr[3],
2781	    pm->pm_sr[4], pm->pm_sr[5], pm->pm_sr[6], pm->pm_sr[7],
2782	    pm->pm_sr[8], pm->pm_sr[9], pm->pm_sr[10], pm->pm_sr[11],
2783	    pm->pm_sr[12], pm->pm_sr[13], pm->pm_sr[14], pm->pm_sr[15]);
2784
2785	return 0;
2786}
2787
2788int
2789pmap_prtrans(u_int pid, vaddr_t va)
2790{
2791	struct proc *p;
2792	pmap_t pm;
2793	struct pmapvp *vp1;
2794	struct pmapvp *vp2;
2795	struct pte_desc *pted;
2796
2797	if (pid == 0) {
2798		pm = pmap_kernel();
2799	} else {
2800		p = pfind(pid);
2801
2802		if (p == NULL) {
2803			db_printf("invalid pid %d", pid);
2804			return 1;
2805		}
2806		pm = p->p_vmspace->vm_map.pmap;
2807	}
2808
2809	db_printf(" pid %d, va 0x%x pmap %x\n", pid, va, pm);
2810	vp1 = pm->pm_vp[VP_SR(va)];
2811	db_printf("sr %x id %x vp1 %x", VP_SR(va), pm->pm_sr[VP_SR(va)],
2812	    vp1);
2813
2814	if (vp1) {
2815		vp2 = vp1->vp[VP_IDX1(va)];
2816		db_printf(" vp2 %x", vp2);
2817
2818		if (vp2) {
2819			pted = vp2->vp[VP_IDX2(va)];
2820			pmap_print_pted(pted, db_printf);
2821
2822		}
2823	}
2824	print_pteg(pm, va);
2825
2826	return 0;
2827}
2828int pmap_show_mappings(paddr_t pa);
2829
2830int
2831pmap_show_mappings(paddr_t pa)
2832{
2833	struct pte_desc *pted;
2834	struct vm_page *pg;
2835
2836	pg = PHYS_TO_VM_PAGE(pa);
2837	if (pg == NULL) {
2838		db_printf("pa %x: unmanaged\n");
2839	} else {
2840		LIST_FOREACH(pted, &(pg->mdpage.pv_list), pted_pv_list) {
2841			pmap_print_pted(pted, db_printf);
2842		}
2843	}
2844	return 0;
2845}
2846#endif
2847