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