1 /* $NetBSD: pmap.c,v 1.201 2023/12/22 19:14:57 thorpej Exp $ */
2 /*
3 * Copyright (c) 1994, 1998, 1999, 2003 Ludd, University of Lule}, Sweden.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.201 2023/12/22 19:14:57 thorpej Exp $");
29
30 #include "opt_cputype.h"
31 #include "opt_ddb.h"
32 #include "opt_lockdebug.h"
33 #include "opt_modular.h"
34 #include "opt_multiprocessor.h"
35 #include "opt_pipe.h"
36
37 #include <sys/param.h>
38
39 #include <sys/atomic.h>
40 #include <sys/buf.h>
41 #include <sys/cpu.h>
42 #include <sys/device.h>
43 #include <sys/extent.h>
44 #include <sys/kmem.h>
45 #include <sys/mutex.h>
46 #include <sys/proc.h>
47 #include <sys/syncobj.h>
48 #include <sys/systm.h>
49
50 #include <uvm/uvm.h>
51 #include <uvm/uvm_physseg.h>
52
53 #ifdef PMAPDEBUG
54 #include <dev/cons.h>
55 #endif
56
57 #include <machine/macros.h>
58 #include <machine/rpb.h>
59 #include <machine/scb.h>
60 #include <machine/sid.h>
61
62 /* QDSS console mapping hack */
63 #include "qd.h"
64 void qdearly(void);
65
66 /*
67 * This code uses bitfield operators for most page table entries.
68 */
69 #define PROTSHIFT 27
70 #define PROT_KW (PG_KW >> PROTSHIFT)
71 #define PROT_KR (PG_KR >> PROTSHIFT)
72 #define PROT_RW (PG_RW >> PROTSHIFT)
73 #define PROT_RO (PG_RO >> PROTSHIFT)
74 #define PROT_URKW (PG_URKW >> PROTSHIFT)
75
76 /*
77 * Scratch pages usage:
78 * Page 1: initial frame pointer during autoconfig. Stack and pcb for
79 * processes during exit on boot CPU only.
80 * Page 2: cpu_info struct for any CPU.
81 * Page 3: unused
82 * Page 4: unused
83 */
84 uintptr_t scratch;
85 #define SCRATCHPAGES 4
86
87
88 static struct pmap kernel_pmap_store;
89 struct pmap *const kernel_pmap_ptr = &kernel_pmap_store;
90
91 struct pte *Sysmap; /* System page table */
92 struct pv_entry *pv_table; /* array of entries, one per LOGICAL page */
93 u_int pventries;
94 u_int pvinuse;
95 vaddr_t iospace;
96
97 vaddr_t ptemapstart, ptemapend;
98 struct extent *ptemap;
99 #define PTMAPSZ EXTENT_FIXED_STORAGE_SIZE(100)
100 char ptmapstorage[PTMAPSZ];
101
102 extern void *msgbufaddr;
103
104 #define IOSPACE_P(p) (((u_long)(p) & 0xe0000000) != 0)
105 #define NPTEPROCSPC 0x1000 /* # of virtual PTEs per process space */
106 #define NPTEPG 0x80 /* # of PTEs per page (logical or physical) */
107 #define PPTESZ sizeof(struct pte)
108 #define NOVADDR 0xffffffff /* Illegal virtual address */
109 #define NPTEPERREG 0x200000
110
111 #define SEGTYPE(x) (((unsigned int)(x)) >> 30)
112 #define P0SEG 0
113 #define P1SEG 1
114 #define SYSSEG 2
115
116 static inline void
pmap_decrement_stats(struct pmap * pm,bool wired)117 pmap_decrement_stats(struct pmap *pm, bool wired)
118 {
119 pm->pm_stats.resident_count--;
120 if (wired)
121 pm->pm_stats.wired_count--;
122 }
123
124 /*
125 * Map in a virtual page.
126 */
127 static inline void
mapin8(int * ptep,long pte)128 mapin8(int *ptep, long pte)
129 {
130 ptep[0] = pte;
131 ptep[1] = pte+1;
132 ptep[2] = pte+2;
133 ptep[3] = pte+3;
134 ptep[4] = pte+4;
135 ptep[5] = pte+5;
136 ptep[6] = pte+6;
137 ptep[7] = pte+7;
138 }
139
140 /*
141 * Check if page table page is in use.
142 */
143 static inline int
ptpinuse(void * pte)144 ptpinuse(void *pte)
145 {
146 int *pve = (int *)vax_trunc_page(pte);
147 int i;
148
149 for (i = 0; i < NPTEPG; i += 8)
150 if (pve[i] != 0)
151 return 1;
152 return 0;
153 }
154
155 #ifdef PMAPDEBUG
156 #define PMDEBUG(x) if (startpmapdebug)printf x
157 #else
158 #define PMDEBUG(x)
159 #endif
160
161 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
162 static kmutex_t pmap_lock;
163 #define PMAP_LOCK mutex_spin_enter(&pmap_lock);
164 #define PMAP_UNLOCK mutex_spin_exit(&pmap_lock);
165 #else
166 #define PMAP_LOCK
167 #define PMAP_UNLOCK
168 #endif
169
170 #ifdef PMAPDEBUG
171 int startpmapdebug = 0;
172 #endif
173
174 paddr_t avail_start, avail_end;
175 vaddr_t virtual_avail, virtual_end; /* Available virtual memory */
176
177 struct pv_entry *get_pventry(void);
178 void free_pventry(struct pv_entry *);
179 void more_pventries(void);
180 vaddr_t get_ptp(void);
181 void free_ptp(paddr_t);
182
183 /*
184 * Calculation of the System Page Table is somewhat a pain, because it
185 * must be in contiguous physical memory and all size calculations must
186 * be done before memory management is turned on.
187 * Arg is usrptsize in ptes.
188 */
189 static vsize_t
calc_kvmsize(vsize_t usrptsize)190 calc_kvmsize(vsize_t usrptsize)
191 {
192 vsize_t kvmsize, bufsz;
193
194 /*
195 * Compute the number of pages kmem_arena will have.
196 */
197 kmeminit_nkmempages();
198
199 /* All physical memory */
200 kvmsize = avail_end;
201 /* User Page table area. This may be large */
202 kvmsize += (usrptsize * sizeof(struct pte));
203 /* Kernel stacks per process */
204 kvmsize += (USPACE * maxproc);
205 /* kernel malloc arena */
206 kvmsize += nkmempages * PAGE_SIZE;
207 /* IO device register space */
208 kvmsize += (IOSPSZ * VAX_NBPG);
209 /* Pager allocations */
210 kvmsize += (pager_map_size + MAXBSIZE);
211 /* Anon pool structures */
212 kvmsize += (physmem * sizeof(struct vm_anon));
213 /* kernel malloc arena */
214 kvmsize += avail_end;
215
216 /* Buffer space - get size of buffer cache and set an upper limit */
217 bufsz = buf_memcalc();
218 buf_setvalimit(bufsz);
219 kvmsize += bufsz;
220
221 /* UBC submap space */
222 kvmsize += (UBC_NWINS << UBC_WINSHIFT);
223
224 /* Exec arg space */
225 kvmsize += NCARGS;
226 #if VAX46 || VAX48 || VAX49 || VAX53 || VAXANY
227 /* Physmap */
228 kvmsize += VM_PHYS_SIZE;
229 #endif
230 #if VAX46 || VAX49
231 kvmsize += 0x800000; /* 8 MB framebuffer */
232 #endif
233 #ifdef MODULAR
234 /* Modules are allocated out of kernel_map */
235 #define MAXLKMSIZ 0x100000 /* XXX */
236 kvmsize += MAXLKMSIZ;
237 #endif
238
239 /* The swapper uses many anon's, set an arbitrary size */
240 #ifndef SWAPSIZE
241 #define SWAPSIZE (200*1024*1024) /* Assume 200MB swap */
242 #endif
243 kvmsize += ((SWAPSIZE/PAGE_SIZE)*sizeof(struct vm_anon));
244
245 /* New pipes may steal some amount of memory. Calculate 10 pipes */
246 #ifndef PIPE_SOCKETPAIR
247 kvmsize += PIPE_DIRECT_CHUNK*10;
248 #endif
249 kvmsize = round_page(kvmsize);
250 return kvmsize;
251 }
252
253 /*
254 * pmap_bootstrap().
255 * Called as part of vm bootstrap, allocates internal pmap structures.
256 * Assumes that nothing is mapped, and that kernel stack is located
257 * immediately after end.
258 */
259 void
pmap_bootstrap(void)260 pmap_bootstrap(void)
261 {
262 struct pcb * const pcb = lwp_getpcb(&lwp0);
263 struct pmap * const pmap = pmap_kernel();
264 struct cpu_info *ci;
265 extern unsigned int etext;
266 unsigned int sysptsize, i;
267 vsize_t kvmsize, usrptsize;
268 vaddr_t istack;
269
270 /* Set logical page size */
271 uvmexp.pagesize = NBPG;
272 uvm_md_init();
273
274 physmem = btoc(avail_end);
275
276 usrptsize = (1024*1024*1024)/VAX_NBPG; /* 1GB total VM */
277 if (vax_btop(usrptsize)* PPTESZ > avail_end/20)
278 usrptsize = (avail_end/(20 * PPTESZ)) * VAX_NBPG;
279
280 kvmsize = calc_kvmsize(usrptsize);
281 /*
282 * Ensure that not more than 1G is allocated, since that is
283 * max size of S0 space.
284 * Also note that for full S0 space the SLR should be 0x200000,
285 * since the comparison in the vax microcode is >= SLR.
286 */
287 #define S0SPACE (1*1024*1024*1024)
288 if (kvmsize > S0SPACE)
289 kvmsize = S0SPACE;
290 sysptsize = kvmsize >> VAX_PGSHIFT;
291 /*
292 * Virtual_* and avail_* is used for mapping of system page table.
293 * The need for kernel virtual memory is linear dependent of the
294 * amount of physical memory also, therefore sysptsize is
295 * a variable here that is changed dependent of the physical
296 * memory size.
297 */
298 virtual_avail = avail_end + KERNBASE;
299 virtual_end = KERNBASE + sysptsize * VAX_NBPG;
300 memset(Sysmap, 0, sysptsize * 4); /* clear SPT before using it */
301
302 /*
303 * The first part of Kernel Virtual memory is the physical
304 * memory mapped in. This makes some mm routines both simpler
305 * and faster, but takes ~0.75% more memory.
306 */
307 pmap_map(KERNBASE, 0, avail_end, VM_PROT_READ|VM_PROT_WRITE);
308 /*
309 * Kernel code is always readable for user, it must be because
310 * of the emulation code that is somewhere in there.
311 * And it doesn't hurt, /netbsd is also public readable.
312 * There are also a couple of other things that must be in
313 * physical memory and that isn't managed by the vm system.
314 */
315 for (i = 0; i < ((unsigned)&etext ^ KERNBASE) >> VAX_PGSHIFT; i++)
316 Sysmap[i].pg_prot = PROT_URKW;
317
318 /* Map System Page Table and zero it, Sysmap already set. */
319 mtpr((unsigned)Sysmap - KERNBASE, PR_SBR);
320
321 /* Map Interrupt stack and set red zone */
322 istack = (uintptr_t)Sysmap + round_page(sysptsize * 4);
323 mtpr(istack + USPACE, PR_ISP);
324 kvtopte(istack)->pg_v = 0;
325
326 /* Some scratch pages */
327 scratch = istack + USPACE;
328
329 /* Physical-to-virtual translation table */
330 pv_table = (struct pv_entry *)(scratch + SCRATCHPAGES * VAX_NBPG);
331
332 avail_start = (vaddr_t)pv_table + (round_page(avail_end >> PGSHIFT)) *
333 sizeof(struct pv_entry) - KERNBASE;
334
335 /* Kernel message buffer */
336 avail_end -= MSGBUFSIZE;
337 msgbufaddr = (void *)(avail_end + KERNBASE);
338
339 /* zero all mapped physical memory from Sysmap to here */
340 memset((void *)istack, 0, (avail_start + KERNBASE) - istack);
341
342 /* QDSS console mapping hack */
343 #if NQD > 0
344 qdearly();
345 #endif
346
347 /* User page table map. This is big. */
348 MAPVIRT(ptemapstart, vax_btoc(usrptsize * sizeof(struct pte)));
349 ptemapend = virtual_avail;
350
351 MAPVIRT(iospace, IOSPSZ); /* Device iospace mapping area */
352
353 /* Init SCB and set up stray vectors. */
354 avail_start = scb_init(avail_start);
355 *(struct rpb *)0 = *(struct rpb *)(uvm_lwp_getuarea(&lwp0) + REDZONEADDR);
356
357 if (dep_call->cpu_steal_pages)
358 (*dep_call->cpu_steal_pages)();
359
360 avail_start = round_page(avail_start);
361 virtual_avail = round_page(virtual_avail);
362 virtual_end = trunc_page(virtual_end);
363
364
365 #if 0 /* Breaks cninit() on some machines */
366 cninit();
367 printf("Sysmap %p, istack %lx, scratch %lx\n",Sysmap,ci->ci_istack,scratch);
368 printf("etext %p, kvmsize %lx\n", &etext, kvmsize);
369 printf("SYSPTSIZE %x usrptsize %lx\n",
370 sysptsize, usrptsize * sizeof(struct pte));
371 printf("pv_table %p, ptemapstart %lx ptemapend %lx\n",
372 pv_table, ptemapstart, ptemapend);
373 printf("avail_start %lx, avail_end %lx\n",avail_start,avail_end);
374 printf("virtual_avail %lx,virtual_end %lx\n",
375 virtual_avail, virtual_end);
376 printf("startpmapdebug %p\n",&startpmapdebug);
377 #endif
378
379
380 /* Init kernel pmap */
381 pmap->pm_p1br = (struct pte *)KERNBASE;
382 pmap->pm_p0br = (struct pte *)KERNBASE;
383 pmap->pm_p1lr = NPTEPERREG;
384 pmap->pm_p0lr = 0;
385 pmap->pm_stats.wired_count = pmap->pm_stats.resident_count = 0;
386 /* btop(virtual_avail - KERNBASE); */
387
388 pmap->pm_count = 1;
389
390 /* Activate the kernel pmap. */
391 pcb->P1BR = pmap->pm_p1br;
392 pcb->P0BR = pmap->pm_p0br;
393 pcb->P1LR = pmap->pm_p1lr;
394 pcb->P0LR = pmap->pm_p0lr|AST_PCB;
395 pcb->pcb_pm = pmap;
396 pcb->pcb_pmnext = pmap->pm_pcbs;
397 pmap->pm_pcbs = pcb;
398 mtpr((uintptr_t)pcb->P1BR, PR_P1BR);
399 mtpr((uintptr_t)pcb->P0BR, PR_P0BR);
400 mtpr(pcb->P1LR, PR_P1LR);
401 mtpr(pcb->P0LR, PR_P0LR);
402
403 /* initialize SSP to point curlwp (lwp0) */
404 pcb->SSP = (uintptr_t)&lwp0;
405 mtpr(pcb->SSP, PR_SSP);
406
407 /* cpu_info struct */
408 ci = (struct cpu_info *) scratch;
409 lwp0.l_cpu = ci;
410 ci->ci_istack = istack;
411 memset(ci, 0, sizeof(*ci));
412 #if defined(MULTIPROCESSOR)
413 ci->ci_curlwp = &lwp0;
414 ci->ci_flags = CI_MASTERCPU|CI_RUNNING;
415 SIMPLEQ_FIRST(&cpus) = ci;
416 #endif
417 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
418 mutex_init(&pmap_lock, MUTEX_DEFAULT, IPL_VM);
419 #endif
420
421 /*
422 * Now everything should be complete, start virtual memory.
423 */
424 uvm_page_physload(avail_start >> PGSHIFT, avail_end >> PGSHIFT,
425 avail_start >> PGSHIFT, avail_end >> PGSHIFT,
426 VM_FREELIST_DEFAULT);
427 mtpr(sysptsize, PR_SLR);
428 rpb.sbr = mfpr(PR_SBR);
429 rpb.slr = mfpr(PR_SLR);
430 rpb.wait = 0; /* DDB signal */
431 mtpr(1, PR_MAPEN);
432 }
433
434 /*
435 * Define the initial bounds of the kernel virtual address space.
436 */
437 void
pmap_virtual_space(vaddr_t * vstartp,vaddr_t * vendp)438 pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp)
439 {
440 *vstartp = virtual_avail;
441 *vendp = virtual_end;
442 }
443
444 /*
445 * Let the VM system do early memory allocation from the direct-mapped
446 * physical memory instead.
447 */
448 vaddr_t
pmap_steal_memory(vsize_t size,vaddr_t * vstartp,vaddr_t * vendp)449 pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp)
450 {
451 vaddr_t v;
452 int npgs;
453 uvm_physseg_t bank;
454
455 PMDEBUG(("pmap_steal_memory: size 0x%lx start %p end %p\n",
456 size, vstartp, vendp));
457
458 size = round_page(size);
459 npgs = btoc(size);
460
461 #ifdef DIAGNOSTIC
462 if (uvm.page_init_done == true)
463 panic("pmap_steal_memory: called _after_ bootstrap");
464 #endif
465
466 /*
467 * A vax only have one segment of memory.
468 */
469 bank = uvm_physseg_get_first();
470
471 v = (uvm_physseg_get_start(bank) << PGSHIFT) | KERNBASE;
472 uvm_physseg_unplug(uvm_physseg_get_start(bank), npgs);
473 memset((void *)v, 0, size);
474 return v;
475 }
476
477 /*
478 * pmap_init() is called as part of vm init after memory management
479 * is enabled. It is meant to do machine-specific allocations.
480 * Here is the resource map for the user page tables inited.
481 */
482 void
pmap_init(void)483 pmap_init(void)
484 {
485 /*
486 * Create the extent map used to manage the page table space.
487 */
488 ptemap = extent_create("ptemap", ptemapstart, ptemapend,
489 ptmapstorage, PTMAPSZ, EX_NOCOALESCE);
490 if (ptemap == NULL)
491 panic("pmap_init");
492 }
493
494 static u_long
pmap_extwrap(vsize_t nsize)495 pmap_extwrap(vsize_t nsize)
496 {
497 int res;
498 u_long rv;
499
500 for (;;) {
501 res = extent_alloc(ptemap, nsize, PAGE_SIZE, 0,
502 EX_WAITOK|EX_MALLOCOK, &rv);
503 if (res == EAGAIN)
504 return 0;
505 if (res == 0)
506 return rv;
507 }
508 }
509
510 /*
511 * Do a page removal from the pv table. A page is identified by its
512 * virtual address combined with its struct pmap in the pv table.
513 */
514 static void
rmpage(pmap_t pm,int * br)515 rmpage(pmap_t pm, int *br)
516 {
517 struct pv_entry *pv, *pl, *pf;
518 vaddr_t vaddr;
519 int found = 0;
520
521 if (pm == pmap_kernel())
522 vaddr = (br - (int *)Sysmap) * VAX_NBPG + 0x80000000;
523 else if ((br >= (int *)pm->pm_p0br) &&
524 (br < ((int *)pm->pm_p0br + pm->pm_p0lr)))
525 vaddr = (br - (int *)pm->pm_p0br) * VAX_NBPG;
526 else
527 vaddr = (br - (int *)pm->pm_p1br) * VAX_NBPG + 0x40000000;
528
529 if (IOSPACE_P((br[0] & PG_FRAME) << VAX_PGSHIFT))
530 return; /* Forget mappings of IO space */
531
532 pv = pv_table + ((br[0] & PG_FRAME) >> LTOHPS);
533 if (((br[0] & PG_PROT) == PG_RW) &&
534 ((pv->pv_attr & PG_M) != PG_M))
535 pv->pv_attr |= br[0]|br[1]|br[2]|br[3]|br[4]|br[5]|br[6]|br[7];
536 pmap_decrement_stats(pm, (br[0] & PG_W) != 0);
537 if (pv->pv_pmap == pm && pv->pv_vaddr == vaddr) {
538 pv->pv_vaddr = NOVADDR;
539 pv->pv_pmap = 0;
540 found++;
541 } else
542 for (pl = pv; pl->pv_next; pl = pl->pv_next) {
543 if (pl->pv_next->pv_pmap != pm ||
544 pl->pv_next->pv_vaddr != vaddr)
545 continue;
546 pf = pl->pv_next;
547 pl->pv_next = pl->pv_next->pv_next;
548 free_pventry(pf);
549 found++;
550 break;
551 }
552 if (found == 0)
553 panic("rmpage: pm %p br %p", pm, br);
554 }
555 /*
556 * Update the PCBs using this pmap after a change.
557 */
558 static void
update_pcbs(struct pmap * pm)559 update_pcbs(struct pmap *pm)
560 {
561 struct pcb *pcb;
562
563 for (pcb = pm->pm_pcbs; pcb != NULL; pcb = pcb->pcb_pmnext) {
564 KASSERT(pcb->pcb_pm == pm);
565 pcb->P0BR = pm->pm_p0br;
566 pcb->P0LR = pm->pm_p0lr | (pcb->P0LR & AST_MASK);
567 pcb->P1BR = pm->pm_p1br;
568 pcb->P1LR = pm->pm_p1lr;
569
570 }
571
572 /* If curlwp uses this pmap update the regs too */
573 if (pm == curproc->p_vmspace->vm_map.pmap) {
574 mtpr((uintptr_t)pm->pm_p0br, PR_P0BR);
575 mtpr(pm->pm_p0lr, PR_P0LR);
576 mtpr((uintptr_t)pm->pm_p1br, PR_P1BR);
577 mtpr(pm->pm_p1lr, PR_P1LR);
578 }
579
580 #if defined(MULTIPROCESSOR) && defined(notyet)
581 /* If someone else is using this pmap, be sure to reread */
582 cpu_send_ipi(IPI_DEST_ALL, IPI_NEWPTE);
583 #endif
584 }
585
586 /*
587 * Allocate a page through direct-mapped segment.
588 */
589 static vaddr_t
getpage(void)590 getpage(void)
591 {
592 struct vm_page *pg;
593
594 pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
595 if (pg == NULL)
596 return 0;
597 return (VM_PAGE_TO_PHYS(pg)|KERNBASE);
598 }
599
600 #if 0
601 /*
602 * Free the page allocated above.
603 */
604 static void
605 freepage(vaddr_t v)
606 {
607 paddr_t paddr = (kvtopte(v)->pg_pfn << VAX_PGSHIFT);
608 uvm_pagefree(PHYS_TO_VM_PAGE(paddr));
609 }
610 #endif
611
612 /*
613 * Remove a full process space. Update all processes pcbs.
614 */
615 static void
rmspace(struct pmap * pm)616 rmspace(struct pmap *pm)
617 {
618 int lr, i, j, *br, *ptpp;
619
620 if (pm->pm_p0lr == 0 && pm->pm_p1lr == NPTEPERREG)
621 return; /* Already free */
622
623 lr = pm->pm_p0lr/NPTEPG;
624 for (i = 0; i < lr; i++) {
625 ptpp = (int *)kvtopte(&pm->pm_p0br[i*NPTEPG]);
626 if (*ptpp == 0)
627 continue;
628 br = (int *)&pm->pm_p0br[i*NPTEPG];
629 for (j = 0; j < NPTEPG; j+=LTOHPN) {
630 if (br[j] == 0)
631 continue;
632 rmpage(pm, &br[j]);
633 }
634 free_ptp((((struct pte *)ptpp)->pg_pfn << VAX_PGSHIFT));
635 *ptpp = 0;
636 mtpr((vaddr_t)br, PR_TBIS);
637 }
638 lr = pm->pm_p1lr/NPTEPG;
639 for (i = lr; i < NPTEPERREG/NPTEPG; i++) {
640 ptpp = (int *)kvtopte(&pm->pm_p1br[i*NPTEPG]);
641 if (*ptpp == 0)
642 continue;
643 br = (int *)&pm->pm_p1br[i*NPTEPG];
644 for (j = 0; j < NPTEPG; j+=LTOHPN) {
645 if (br[j] == 0)
646 continue;
647 rmpage(pm, &br[j]);
648 }
649 free_ptp((((struct pte *)ptpp)->pg_pfn << VAX_PGSHIFT));
650 *ptpp = 0;
651 mtpr((vaddr_t)br, PR_TBIS);
652 }
653
654 if (pm->pm_p0lr != 0)
655 extent_free(ptemap, (u_long)pm->pm_p0br,
656 pm->pm_p0lr * PPTESZ, EX_WAITOK);
657 if (pm->pm_p1lr != NPTEPERREG)
658 extent_free(ptemap, (u_long)pm->pm_p1ap,
659 (NPTEPERREG - pm->pm_p1lr) * PPTESZ, EX_WAITOK);
660 pm->pm_p0br = pm->pm_p1br = (struct pte *)KERNBASE;
661 pm->pm_p0lr = 0;
662 pm->pm_p1lr = NPTEPERREG;
663 pm->pm_p1ap = NULL;
664 update_pcbs(pm);
665 }
666
667 /*
668 * Find a process to remove the process space for. *sigh*
669 * Avoid to remove ourselves.
670 */
671
672 static inline bool
pmap_vax_swappable(struct lwp * l,struct pmap * pm)673 pmap_vax_swappable(struct lwp *l, struct pmap *pm)
674 {
675
676 if (l->l_flag & (LW_SYSTEM | LW_WEXIT))
677 return false;
678 if (l->l_proc->p_vmspace->vm_map.pmap == pm)
679 return false;
680 if ((l->l_pflag & LP_RUNNING) != 0)
681 return false;
682 if (l->l_class != SCHED_OTHER)
683 return false;
684 if (l->l_syncobj == &rw_syncobj || l->l_syncobj == &mutex_syncobj)
685 return false;
686 if (l->l_proc->p_stat != SACTIVE && l->l_proc->p_stat != SSTOP)
687 return false;
688 return true;
689 }
690
691 static int
pmap_rmproc(struct pmap * pm)692 pmap_rmproc(struct pmap *pm)
693 {
694 struct pmap *ppm;
695 struct lwp *l;
696 struct lwp *outl, *outl2;
697 int outpri, outpri2;
698 int didswap = 0;
699 extern int maxslp;
700
701 outl = outl2 = NULL;
702 outpri = outpri2 = 0;
703 mutex_enter(&proc_lock);
704 LIST_FOREACH(l, &alllwp, l_list) {
705 if (!pmap_vax_swappable(l, pm))
706 continue;
707 ppm = l->l_proc->p_vmspace->vm_map.pmap;
708 if (ppm->pm_p0lr == 0 && ppm->pm_p1lr == NPTEPERREG)
709 continue; /* Already swapped */
710 switch (l->l_stat) {
711 case LSRUN:
712 case LSONPROC:
713 if (l->l_swtime > outpri2) {
714 outl2 = l;
715 outpri2 = l->l_swtime;
716 }
717 continue;
718 case LSSLEEP:
719 case LSSTOP:
720 if (l->l_slptime >= maxslp) {
721 rmspace(l->l_proc->p_vmspace->vm_map.pmap);
722 didswap++;
723 } else if (l->l_slptime > outpri) {
724 outl = l;
725 outpri = l->l_slptime;
726 }
727 continue;
728 }
729 }
730 mutex_exit(&proc_lock);
731 if (didswap == 0) {
732 if ((l = outl) == NULL)
733 l = outl2;
734 if (l) {
735 rmspace(l->l_proc->p_vmspace->vm_map.pmap);
736 didswap++;
737 }
738 }
739 return didswap;
740 }
741
742 /*
743 * Allocate space for user page tables, from ptemap.
744 * Argument is needed space, in bytes.
745 * Returns a pointer to the newly allocated space, or 0 if failed.
746 */
747 static vaddr_t
pmap_getusrptes(pmap_t pm,vsize_t nsize)748 pmap_getusrptes(pmap_t pm, vsize_t nsize)
749 {
750 u_long rv;
751
752 #ifdef DEBUG
753 if (nsize & PAGE_MASK)
754 panic("pmap_getusrptes: bad size %lx", nsize);
755 #endif
756 while (((rv = pmap_extwrap(nsize)) == 0) && (pmap_rmproc(pm) != 0))
757 ;
758 return rv;
759 }
760
761 /*
762 * Remove a pte page when all references are gone.
763 */
764 static void
rmptep(struct pte * pte)765 rmptep(struct pte *pte)
766 {
767 int *ptpp = (int *)kvtopte(pte);
768 #ifdef DEBUG
769 { int i, *ptr = (int *)vax_trunc_page(pte);
770 for (i = 0; i < NPTEPG; i++)
771 if (ptr[i] != 0)
772 panic("rmptep: ptr[%d] != 0", i);
773 }
774 #endif
775 free_ptp((((struct pte *)ptpp)->pg_pfn << VAX_PGSHIFT));
776 *ptpp = 0;
777 /* N.B. callers all do a TBIA, so TBIS not needed here. */
778 }
779
780 static int
grow_p0(struct pmap * pm,int reqlen)781 grow_p0(struct pmap *pm, int reqlen)
782 {
783 vaddr_t nptespc;
784 char *from, *to;
785 int srclen, dstlen;
786 int inuse, len, p0lr;
787 u_long p0br;
788
789 PMDEBUG(("grow_p0: pmap %p reqlen %d\n", pm, reqlen));
790
791 /* Get new pte space */
792 p0lr = pm->pm_p0lr;
793 inuse = p0lr != 0;
794 len = round_page((reqlen+1) * PPTESZ);
795 PMAP_UNLOCK;
796 nptespc = pmap_getusrptes(pm, len);
797 PMAP_LOCK;
798
799 if (nptespc == 0)
800 return 0;
801 /*
802 * Copy the old ptes to the new space.
803 * Done by moving on system page table.
804 */
805 srclen = vax_btop(p0lr * PPTESZ) * PPTESZ;
806 dstlen = vax_btoc(len)*PPTESZ;
807 from = (char *)kvtopte(pm->pm_p0br);
808 to = (char *)kvtopte(nptespc);
809
810 PMDEBUG(("grow_p0: from %p to %p src %d dst %d\n",
811 from, to, srclen, dstlen));
812
813 if (inuse)
814 memcpy(to, from, srclen);
815 memset(to+srclen, 0, dstlen-srclen);
816 p0br = (u_long)pm->pm_p0br;
817 pm->pm_p0br = (struct pte *)nptespc;
818 pm->pm_p0lr = (len/PPTESZ);
819 update_pcbs(pm);
820
821 /* Remove the old after update_pcbs() (for multi-CPU propagation) */
822 if (inuse)
823 extent_free(ptemap, p0br, p0lr*PPTESZ, EX_WAITOK);
824 return 1;
825 }
826
827
828 static int
grow_p1(struct pmap * pm,int len)829 grow_p1(struct pmap *pm, int len)
830 {
831 vaddr_t nptespc, optespc;
832 int nlen, olen;
833
834 PMDEBUG(("grow_p1: pm %p len %x\n", pm, len));
835
836 /* Get new pte space */
837 nlen = (NPTEPERREG*PPTESZ) - trunc_page(len * PPTESZ);
838 PMAP_UNLOCK;
839 nptespc = pmap_getusrptes(pm, nlen);
840 PMAP_LOCK;
841 if (nptespc == 0)
842 return 0;
843
844 olen = (NPTEPERREG*PPTESZ) - (pm->pm_p1lr * PPTESZ);
845 optespc = (vaddr_t)pm->pm_p1ap;
846
847 /*
848 * Copy the old ptes to the new space.
849 * Done by moving on system page table.
850 */
851 memset(kvtopte(nptespc), 0, vax_btop(nlen-olen) * PPTESZ);
852 if (optespc)
853 memcpy(kvtopte(nptespc+nlen-olen), kvtopte(optespc),
854 vax_btop(olen) * PPTESZ);
855
856 pm->pm_p1ap = (struct pte *)nptespc;
857 pm->pm_p1br = (struct pte *)(nptespc+nlen-(NPTEPERREG*PPTESZ));
858 pm->pm_p1lr = NPTEPERREG - nlen/PPTESZ;
859 update_pcbs(pm);
860
861 if (optespc)
862 extent_free(ptemap, optespc, olen, EX_WAITOK);
863 return 1;
864 }
865
866 /*
867 * Initialize a preallocated and zeroed pmap structure,
868 */
869 static void
pmap_pinit(pmap_t pmap)870 pmap_pinit(pmap_t pmap)
871 {
872
873 /*
874 * Do not allocate any pte's here, we don't know the size and
875 * we'll get a page fault anyway when some page is referenced,
876 * so do it then.
877 */
878 pmap->pm_p0br = (struct pte *)KERNBASE;
879 pmap->pm_p1br = (struct pte *)KERNBASE;
880 pmap->pm_p0lr = 0;
881 pmap->pm_p1lr = NPTEPERREG;
882 pmap->pm_p1ap = NULL;
883
884 PMDEBUG(("pmap_pinit(%p): p0br=%p p0lr=0x%lx p1br=%p p1lr=0x%lx\n",
885 pmap, pmap->pm_p0br, pmap->pm_p0lr, pmap->pm_p1br, pmap->pm_p1lr));
886
887 pmap->pm_count = 1;
888 pmap->pm_stats.resident_count = pmap->pm_stats.wired_count = 0;
889 }
890
891 /*
892 * pmap_create() creates a pmap for a new task.
893 * If not already allocated, allocate space for one.
894 */
895 struct pmap *
pmap_create(void)896 pmap_create(void)
897 {
898 struct pmap *pmap;
899
900 pmap = kmem_zalloc(sizeof(*pmap), KM_SLEEP);
901 pmap_pinit(pmap);
902 return pmap;
903 }
904
905 /*
906 * Release any resources held by the given physical map.
907 * Called when a pmap initialized by pmap_pinit is being released.
908 * Should only be called if the map contains no valid mappings.
909 */
910 static void
pmap_release(struct pmap * pmap)911 pmap_release(struct pmap *pmap)
912 {
913 #ifdef DEBUG
914 vaddr_t saddr, eaddr;
915 #endif
916
917 PMDEBUG(("pmap_release: pmap %p\n",pmap));
918
919 if (pmap->pm_p0br == 0)
920 return;
921
922 #ifdef DEBUG
923 #if 0
924 for (i = 0; i < NPTEPROCSPC; i++)
925 if (pmap->pm_pref[i])
926 panic("pmap_release: refcnt %d index %d",
927 pmap->pm_pref[i], i);
928 #endif
929
930 saddr = (vaddr_t)pmap->pm_p0br;
931 eaddr = saddr + pmap->pm_p0lr * PPTESZ;
932 for (; saddr < eaddr; saddr += PAGE_SIZE)
933 if (kvtopte(saddr)->pg_pfn)
934 panic("pmap_release: P0 page mapped");
935 saddr = (vaddr_t)pmap->pm_p1br + pmap->pm_p1lr * PPTESZ;
936 eaddr = KERNBASE;
937 for (; saddr < eaddr; saddr += PAGE_SIZE)
938 if (kvtopte(saddr)->pg_pfn)
939 panic("pmap_release: P1 page mapped");
940 #endif
941 if (pmap->pm_p0lr != 0)
942 extent_free(ptemap, (u_long)pmap->pm_p0br,
943 pmap->pm_p0lr * PPTESZ, EX_WAITOK);
944 if (pmap->pm_p1lr != NPTEPERREG)
945 extent_free(ptemap, (u_long)pmap->pm_p1ap,
946 (NPTEPERREG - pmap->pm_p1lr) * PPTESZ, EX_WAITOK);
947 }
948
949 /*
950 * pmap_destroy(pmap): Remove a reference from the pmap.
951 * If the pmap is NULL then just return else decrease pm_count.
952 * If this was the last reference we call's pmap_release to release this pmap.
953 */
954
955 void
pmap_destroy(pmap_t pmap)956 pmap_destroy(pmap_t pmap)
957 {
958 PMDEBUG(("pmap_destroy: pmap %p\n",pmap));
959
960 if (atomic_dec_uint_nv(&pmap->pm_count) == 0) {
961 #ifdef DIAGNOSTIC
962 if (pmap->pm_pcbs)
963 panic("pmap_destroy used pmap");
964 #endif
965 pmap_release(pmap);
966 kmem_free(pmap, sizeof(*pmap));
967 }
968 }
969
970 static struct pte *
vaddrtopte(const struct pv_entry * pv)971 vaddrtopte(const struct pv_entry *pv)
972 {
973 struct pmap *pm;
974 if (pv->pv_pmap == NULL || pv->pv_vaddr == NOVADDR)
975 return NULL;
976 if (pv->pv_vaddr & KERNBASE)
977 return &Sysmap[(pv->pv_vaddr & ~KERNBASE) >> VAX_PGSHIFT];
978 pm = pv->pv_pmap;
979 if (pv->pv_vaddr & 0x40000000)
980 return &pm->pm_p1br[vax_btop(pv->pv_vaddr & ~0x40000000)];
981 else
982 return &pm->pm_p0br[vax_btop(pv->pv_vaddr)];
983 }
984
985 /*
986 * New (real nice!) function that allocates memory in kernel space
987 * without tracking it in the MD code.
988 */
989 void
pmap_kenter_pa(vaddr_t va,paddr_t pa,vm_prot_t prot,u_int flags)990 pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags)
991 {
992 int *ptp, opte;
993
994 ptp = (int *)kvtopte(va);
995 PMDEBUG(("pmap_kenter_pa: va: %lx, pa %lx, prot %x ptp %p\n",
996 va, pa, prot, ptp));
997 opte = ptp[0];
998 ptp[0] = PG_V | ((prot & VM_PROT_WRITE)? PG_KW : PG_KR) |
999 PG_PFNUM(pa) | PG_SREF;
1000 ptp[1] = ptp[0] + 1;
1001 ptp[2] = ptp[0] + 2;
1002 ptp[3] = ptp[0] + 3;
1003 ptp[4] = ptp[0] + 4;
1004 ptp[5] = ptp[0] + 5;
1005 ptp[6] = ptp[0] + 6;
1006 ptp[7] = ptp[0] + 7;
1007 if (opte & PG_V) {
1008 #if defined(MULTIPROCESSOR)
1009 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA);
1010 #endif
1011 mtpr(0, PR_TBIA);
1012 }
1013 }
1014
1015 void
pmap_kremove(vaddr_t va,vsize_t len)1016 pmap_kremove(vaddr_t va, vsize_t len)
1017 {
1018 struct pte *pte;
1019 #ifdef PMAPDEBUG
1020 int i;
1021 #endif
1022
1023 PMDEBUG(("pmap_kremove: va: %lx, len %lx, ptp %p\n",
1024 va, len, kvtopte(va)));
1025
1026 pte = kvtopte(va);
1027
1028 #ifdef PMAPDEBUG
1029 /*
1030 * Check if any pages are on the pv list.
1031 * This shouldn't happen anymore.
1032 */
1033 len >>= PGSHIFT;
1034 for (i = 0; i < len; i++) {
1035 if (pte->pg_pfn == 0)
1036 continue;
1037 if (pte->pg_sref == 0)
1038 panic("pmap_kremove");
1039 memset(pte, 0, LTOHPN * sizeof(struct pte));
1040 pte += LTOHPN;
1041 }
1042 #else
1043 len >>= VAX_PGSHIFT;
1044 memset(pte, 0, len * sizeof(struct pte));
1045 #endif
1046 #if defined(MULTIPROCESSOR)
1047 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA);
1048 #endif
1049 mtpr(0, PR_TBIA);
1050 }
1051
1052 /*
1053 * pmap_enter() is the main routine that puts in mappings for pages, or
1054 * upgrades mappings to more "rights".
1055 */
1056 int
pmap_enter(pmap_t pmap,vaddr_t v,paddr_t p,vm_prot_t prot,u_int flags)1057 pmap_enter(pmap_t pmap, vaddr_t v, paddr_t p, vm_prot_t prot, u_int flags)
1058 {
1059 struct pv_entry *pv, *tmp;
1060 int newpte, oldpte;
1061 int *pteptr; /* current pte to write mapping info to */
1062 int *ptpptr; /* ptr to page table page */
1063
1064
1065 PMDEBUG(("pmap_enter: pmap %p v %lx p %lx prot %x wired %d access %x\n",
1066 pmap, v, p, prot, (flags & PMAP_WIRED) != 0, flags & VM_PROT_ALL));
1067
1068 PMAP_LOCK;
1069
1070 /* Find address of correct pte */
1071 switch (SEGTYPE(v)) {
1072 case SYSSEG:
1073 pteptr = ((int *)Sysmap) + vax_btop(v - KERNBASE);
1074 newpte = (prot & VM_PROT_WRITE ? PG_KW : PG_KR);
1075 break;
1076
1077 case P0SEG:
1078 if (vax_btop(v) >= pmap->pm_p0lr)
1079 if (grow_p0(pmap, vax_btop(v)) == 0)
1080 goto growfail;
1081 pteptr = (int *)pmap->pm_p0br + vax_btop(v);
1082 newpte = (prot & VM_PROT_WRITE ? PG_RW : PG_RO);
1083 break;
1084
1085 case P1SEG:
1086 if (vax_btop(v - 0x40000000) < pmap->pm_p1lr)
1087 if (grow_p1(pmap, vax_btop(v - 0x40000000)) == 0)
1088 goto growfail;
1089 pteptr = (int *)pmap->pm_p1br + vax_btop(v - 0x40000000);
1090 newpte = (prot & VM_PROT_WRITE ? PG_RW : PG_RO);
1091 break;
1092 default:
1093 panic("bad seg");
1094 }
1095 newpte |= vax_btop(p);
1096
1097 if (SEGTYPE(v) != SYSSEG) {
1098 /*
1099 * Check if a pte page must be mapped in.
1100 */
1101 ptpptr = (int *)kvtopte(pteptr);
1102
1103 if (*ptpptr == 0) {
1104 paddr_t phys;
1105
1106 phys = get_ptp();
1107 if (phys == 0) {
1108 PMAP_UNLOCK;
1109 if ((flags & PMAP_CANFAIL) != 0)
1110 return ENOMEM;
1111 panic("pmap_enter: out of memory");
1112 }
1113 *ptpptr = PG_V | PG_KW | PG_PFNUM(phys);
1114 }
1115 }
1116
1117 /*
1118 * Do not keep track of anything if mapping IO space.
1119 */
1120 if (IOSPACE_P(p)) {
1121 mapin8(pteptr, newpte);
1122 PMAP_UNLOCK;
1123 return 0;
1124 }
1125
1126 if (flags & PMAP_WIRED)
1127 newpte |= PG_W;
1128
1129 oldpte = *pteptr & ~(PG_V|PG_M);
1130 pv = pv_table + (p >> PGSHIFT);
1131
1132 /* just a wiring change? */
1133 if (newpte == (oldpte | PG_W)) {
1134 *pteptr |= PG_W;
1135 pmap->pm_stats.wired_count++;
1136 PMAP_UNLOCK;
1137 return 0;
1138 }
1139
1140 /* mapping unchanged? just return. */
1141 if (newpte == oldpte) {
1142 PMAP_UNLOCK;
1143 return 0;
1144 }
1145
1146 /* Changing mapping? */
1147
1148 if ((newpte & PG_FRAME) == (oldpte & PG_FRAME)) {
1149 /* prot change. resident_count will be increased later */
1150 pmap_decrement_stats(pmap, (oldpte & PG_W) != 0);
1151 } else {
1152
1153 /*
1154 * Mapped before? Remove it then.
1155 */
1156
1157 if (oldpte & PG_FRAME) {
1158 if ((oldpte & PG_SREF) == 0)
1159 rmpage(pmap, pteptr);
1160 else {
1161 PMAP_UNLOCK;
1162 panic("pmap_enter on PG_SREF page");
1163 }
1164 }
1165
1166 if (pv->pv_pmap == NULL) {
1167 pv->pv_vaddr = v;
1168 pv->pv_pmap = pmap;
1169 } else {
1170 tmp = get_pventry();
1171 tmp->pv_vaddr = v;
1172 tmp->pv_pmap = pmap;
1173 tmp->pv_next = pv->pv_next;
1174 pv->pv_next = tmp;
1175 }
1176 }
1177 pmap->pm_stats.resident_count++;
1178 if ((flags & PMAP_WIRED) != 0)
1179 pmap->pm_stats.wired_count++;
1180
1181 if (flags & (VM_PROT_READ|VM_PROT_WRITE)) {
1182 pv->pv_attr |= PG_V;
1183 newpte |= PG_V;
1184 }
1185 if (flags & VM_PROT_WRITE)
1186 pv->pv_attr |= PG_M;
1187
1188 if (flags & PMAP_WIRED)
1189 newpte |= PG_V; /* Not allowed to be invalid */
1190
1191 mapin8(pteptr, newpte);
1192
1193 if (pventries < 10)
1194 more_pventries();
1195
1196 PMAP_UNLOCK;
1197
1198 mtpr(0, PR_TBIA); /* Always; safety belt */
1199 return 0;
1200
1201 growfail:
1202 PMAP_UNLOCK;
1203 if (flags & PMAP_CANFAIL)
1204 return ENOMEM;
1205 panic("usrptmap space leakage");
1206 }
1207
1208 vaddr_t
pmap_map(vaddr_t virtual,paddr_t pstart,paddr_t pend,int prot)1209 pmap_map(vaddr_t virtual, paddr_t pstart, paddr_t pend, int prot)
1210 {
1211 vaddr_t count;
1212 int *pentry;
1213
1214 PMDEBUG(("pmap_map: virt %lx, pstart %lx, pend %lx, Sysmap %p\n",
1215 virtual, pstart, pend, Sysmap));
1216
1217 pstart &= 0x7fffffffUL;
1218 pend &= 0x7fffffffUL;
1219 virtual &= 0x7fffffffUL;
1220 pentry = &((int *)Sysmap)[virtual >> VAX_PGSHIFT];
1221 for (count = pstart; count < pend; count += VAX_NBPG) {
1222 *pentry++ = (count >> VAX_PGSHIFT)|PG_V|
1223 (prot & VM_PROT_WRITE ? PG_KW : PG_KR);
1224 }
1225 return virtual + (count - pstart) + KERNBASE;
1226 }
1227
1228 #if 0
1229 bool
1230 pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap)
1231 {
1232 paddr_t pa = 0;
1233 int *pte, sva;
1234
1235 PMDEBUG(("pmap_extract: pmap %p, va %lx\n",pmap, va));
1236
1237 if (va & KERNBASE) {
1238 pa = kvtophys(va); /* Is 0 if not mapped */
1239 if (pap)
1240 *pap = pa;
1241 if (pa)
1242 return (true);
1243 return (false);
1244 }
1245
1246 sva = PG_PFNUM(va);
1247 if (va < 0x40000000) {
1248 if (sva > pmap->pm_p0lr)
1249 return false;
1250 pte = (int *)pmap->pm_p0br;
1251 } else {
1252 if (sva < pmap->pm_p1lr)
1253 return false;
1254 pte = (int *)pmap->pm_p1br;
1255 }
1256 if (kvtopte(&pte[sva])->pg_pfn) {
1257 if (pap)
1258 *pap = (pte[sva] & PG_FRAME) << VAX_PGSHIFT;
1259 return (true);
1260 }
1261 return (false);
1262 }
1263 #endif
1264 /*
1265 * Sets protection for a given region to prot. If prot == none then
1266 * unmap region. pmap_remove is implemented as pmap_protect with
1267 * protection none.
1268 */
1269 void
pmap_protect_long(pmap_t pmap,vaddr_t start,vaddr_t end,vm_prot_t prot)1270 pmap_protect_long(pmap_t pmap, vaddr_t start, vaddr_t end, vm_prot_t prot)
1271 {
1272 struct pte *pt, *pts, *ptd;
1273 int pr, lr;
1274
1275 PMDEBUG(("pmap_protect: pmap %p, start %lx, end %lx, prot %x\n",
1276 pmap, start, end,prot));
1277
1278 PMAP_LOCK;
1279
1280 switch (SEGTYPE(start)) {
1281 case SYSSEG:
1282 pt = Sysmap;
1283 #ifdef DIAGNOSTIC
1284 if (((end & 0x3fffffff) >> VAX_PGSHIFT) > mfpr(PR_SLR))
1285 panic("pmap_protect: outside SLR: %lx", end);
1286 #endif
1287 start &= ~KERNBASE;
1288 end &= ~KERNBASE;
1289 pr = (prot & VM_PROT_WRITE ? PROT_KW : PROT_KR);
1290 break;
1291
1292 case P1SEG:
1293 if (vax_btop(end - 0x40000000) <= pmap->pm_p1lr) {
1294 PMAP_UNLOCK;
1295 return;
1296 }
1297 if (vax_btop(start - 0x40000000) < pmap->pm_p1lr)
1298 start = pmap->pm_p1lr * VAX_NBPG;
1299 pt = pmap->pm_p1br;
1300 start &= 0x3fffffff;
1301 end = (end == KERNBASE ? end >> 1 : end & 0x3fffffff);
1302 pr = (prot & VM_PROT_WRITE ? PROT_RW : PROT_RO);
1303 break;
1304
1305 case P0SEG:
1306 lr = pmap->pm_p0lr;
1307
1308 /* Anything to care about at all? */
1309 if (vax_btop(start) > lr) {
1310 PMAP_UNLOCK;
1311 return;
1312 }
1313 if (vax_btop(end) > lr)
1314 end = lr * VAX_NBPG;
1315 pt = pmap->pm_p0br;
1316 pr = (prot & VM_PROT_WRITE ? PROT_RW : PROT_RO);
1317 break;
1318 default:
1319 panic("unsupported segtype: %d", SEGTYPE(start));
1320 }
1321
1322 pts = &pt[start >> VAX_PGSHIFT];
1323 ptd = &pt[end >> VAX_PGSHIFT];
1324 #ifdef DEBUG
1325 if (((int)pts - (int)pt) & 7)
1326 panic("pmap_remove: pts not even");
1327 if (((int)ptd - (int)pt) & 7)
1328 panic("pmap_remove: ptd not even");
1329 #endif
1330
1331 while (pts < ptd) {
1332 if (kvtopte(pts)->pg_pfn && *(int *)pts) {
1333 if (prot == VM_PROT_NONE) {
1334 if ((*(int *)pts & PG_SREF) == 0)
1335 rmpage(pmap, (u_int *)pts);
1336 #ifdef DEBUG
1337 else {
1338 PMAP_UNLOCK;
1339 panic("pmap_remove PG_SREF page");
1340 }
1341 #endif
1342 memset(pts, 0, sizeof(struct pte) * LTOHPN);
1343 if (pt != Sysmap) {
1344 if (ptpinuse(pts) == 0)
1345 rmptep(pts);
1346 }
1347 } else {
1348 pts[0].pg_prot = pr;
1349 pts[1].pg_prot = pr;
1350 pts[2].pg_prot = pr;
1351 pts[3].pg_prot = pr;
1352 pts[4].pg_prot = pr;
1353 pts[5].pg_prot = pr;
1354 pts[6].pg_prot = pr;
1355 pts[7].pg_prot = pr;
1356 }
1357 }
1358 pts += LTOHPN;
1359 }
1360 PMAP_UNLOCK;
1361 #ifdef MULTIPROCESSOR
1362 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA);
1363 #endif
1364 mtpr(0, PR_TBIA);
1365 }
1366
1367 int pmap_simulref(int bits, int addr);
1368
1369 /*
1370 * Called from interrupt vector routines if we get a page invalid fault.
1371 * Note: the save mask must be or'ed with 0x3f for this function.
1372 * Returns 0 if normal call, 1 if CVAX bug detected.
1373 */
1374 int
pmap_simulref(int bits,int addr)1375 pmap_simulref(int bits, int addr)
1376 {
1377 u_int *pte;
1378 struct pv_entry *pv;
1379 paddr_t pa;
1380
1381 PMDEBUG(("pmap_simulref: bits %x addr %x\n", bits, addr));
1382
1383 #ifdef DEBUG
1384 if (bits & 1)
1385 panic("pte trans len");
1386 #endif
1387 /* Set address on logical page boundary */
1388 addr &= ~PGOFSET;
1389 /* First decode userspace addr */
1390 if (addr >= 0) {
1391 if ((addr << 1) < 0)
1392 pte = (u_int *)mfpr(PR_P1BR);
1393 else
1394 pte = (u_int *)mfpr(PR_P0BR);
1395 pte += PG_PFNUM(addr);
1396 if (bits & 2) { /* PTE reference */
1397 pte = (u_int *)kvtopte(vax_trunc_page(pte));
1398 if (pte[0] == 0) /* Check for CVAX bug */
1399 return 1;
1400 panic("pmap_simulref");
1401 pa = (u_int)pte & ~KERNBASE;
1402 } else
1403 pa = Sysmap[PG_PFNUM(pte)].pg_pfn << VAX_PGSHIFT;
1404 } else {
1405 pte = (u_int *)kvtopte(addr);
1406 pa = (u_int)pte & ~KERNBASE;
1407 }
1408 pte[0] |= PG_V;
1409 pte[1] |= PG_V;
1410 pte[2] |= PG_V;
1411 pte[3] |= PG_V;
1412 pte[4] |= PG_V;
1413 pte[5] |= PG_V;
1414 pte[6] |= PG_V;
1415 pte[7] |= PG_V;
1416 if (!IOSPACE_P(pa)) { /* No pv_table fiddling in iospace */
1417 PMAP_LOCK;
1418 pv = pv_table + (pa >> PGSHIFT);
1419 pv->pv_attr |= PG_V; /* Referenced */
1420 if (bits & 4) /* (will be) modified. XXX page tables */
1421 pv->pv_attr |= PG_M;
1422 PMAP_UNLOCK;
1423 }
1424 return 0;
1425 }
1426
1427 /*
1428 * Clears valid bit in all ptes referenced to this physical page.
1429 */
1430 bool
pmap_clear_reference(struct vm_page * pg)1431 pmap_clear_reference(struct vm_page *pg)
1432 {
1433 struct pv_entry *pv = pmap_pg_to_pv(pg);
1434 struct pte *pte;
1435 bool ref;
1436
1437 PMDEBUG(("pmap_clear_reference: pv_entry %p\n", pv));
1438
1439 PMAP_LOCK;
1440 ref = ISSET(pv->pv_attr, PG_V);
1441 CLR(pv->pv_attr, PG_V);
1442 if (pv->pv_pmap != NULL) do {
1443 pte = vaddrtopte(pv);
1444 if (pte[0].pg_w == 0) {
1445 pte[0].pg_v = 0; pte[1].pg_v = 0;
1446 pte[2].pg_v = 0; pte[3].pg_v = 0;
1447 pte[4].pg_v = 0; pte[5].pg_v = 0;
1448 pte[6].pg_v = 0; pte[7].pg_v = 0;
1449 }
1450 } while ((pv = pv->pv_next) != NULL);
1451 PMAP_UNLOCK;
1452 #ifdef MULTIPROCESSOR
1453 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA);
1454 #endif
1455 mtpr(0, PR_TBIA);
1456 return ref;
1457 }
1458
1459 /*
1460 * Checks if page is modified; returns true or false depending on result.
1461 */
1462 bool
pmap_is_modified(struct vm_page * pg)1463 pmap_is_modified(struct vm_page *pg)
1464 {
1465 struct pv_entry *pv = pmap_pg_to_pv(pg);
1466 bool rv;
1467
1468 PMDEBUG(("pmap_is_modified: pv_entry %p ", pv));
1469
1470 PMAP_LOCK;
1471 rv = ISSET(pv->pv_attr, PG_M);
1472 if (rv == false && pv->pv_pmap != NULL) do {
1473 const struct pte * const pte = vaddrtopte(pv);
1474 if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m
1475 | pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) {
1476 rv = true;
1477 SET(pv->pv_attr, PG_M);
1478 break;
1479 }
1480 } while ((pv = pv->pv_next) != NULL);
1481 PMAP_UNLOCK;
1482 return rv;
1483 }
1484
1485 /*
1486 * Clears modify bit in all ptes referenced to this physical page.
1487 */
1488 bool
pmap_clear_modify(struct vm_page * pg)1489 pmap_clear_modify(struct vm_page *pg)
1490 {
1491 struct pv_entry *pv = pmap_pg_to_pv(pg);
1492 bool rv = false;
1493
1494 PMDEBUG(("pmap_clear_modify: pv_entry %p\n", pv));
1495
1496 PMAP_LOCK;
1497 rv = ISSET(pv->pv_attr, PG_M);
1498 CLR(pv->pv_attr, PG_M);
1499 if (pv->pv_pmap != NULL) do {
1500 struct pte * const pte = vaddrtopte(pv);
1501 if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m |
1502 pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) {
1503 rv = true;
1504 }
1505 pte[0].pg_m = pte[1].pg_m = pte[2].pg_m = pte[3].pg_m = 0;
1506 pte[4].pg_m = pte[5].pg_m = pte[6].pg_m = pte[7].pg_m = 0;
1507 } while ((pv = pv->pv_next) != NULL);
1508 PMAP_UNLOCK;
1509 return rv;
1510 }
1511
1512 /*
1513 * Lower the permission for all mappings to a given page.
1514 * Lower permission can only mean setting protection to either read-only
1515 * or none; where none is unmapping of the page.
1516 */
1517 void
pmap_page_protect_long(struct pv_entry * pv,vm_prot_t prot)1518 pmap_page_protect_long(struct pv_entry *pv, vm_prot_t prot)
1519 {
1520 struct pte *pt;
1521 struct pv_entry *opv, *pl;
1522 int *g;
1523
1524 PMDEBUG(("pmap_page_protect: pv %p, prot %x\n", pv, prot));
1525
1526 if (prot == VM_PROT_ALL) /* 'cannot happen' */
1527 return;
1528
1529 PMAP_LOCK;
1530 if (prot == VM_PROT_NONE) {
1531 g = (int *)vaddrtopte(pv);
1532 if (g) {
1533 pmap_decrement_stats(pv->pv_pmap, (g[0] & PG_W) != 0);
1534 if ((pv->pv_attr & (PG_V|PG_M)) != (PG_V|PG_M))
1535 pv->pv_attr |=
1536 g[0]|g[1]|g[2]|g[3]|g[4]|g[5]|g[6]|g[7];
1537 memset(g, 0, sizeof(struct pte) * LTOHPN);
1538 if (pv->pv_pmap != pmap_kernel()) {
1539 if (ptpinuse(g) == 0)
1540 rmptep((void *)g);
1541 }
1542 pv->pv_vaddr = NOVADDR;
1543 pv->pv_pmap = NULL;
1544 }
1545 pl = pv->pv_next;
1546 pv->pv_pmap = 0;
1547 pv->pv_next = 0;
1548 while (pl) {
1549 g = (int *)vaddrtopte(pl);
1550 pmap_decrement_stats(pl->pv_pmap, (g[0] & PG_W) != 0);
1551 if ((pv->pv_attr & (PG_V|PG_M)) != (PG_V|PG_M))
1552 pv->pv_attr |=
1553 g[0]|g[1]|g[2]|g[3]|g[4]|g[5]|g[6]|g[7];
1554 memset(g, 0, sizeof(struct pte) * LTOHPN);
1555 if (pl->pv_pmap != pmap_kernel()) {
1556 if (ptpinuse(g) == 0)
1557 rmptep((void *)g);
1558 }
1559 opv = pl;
1560 pl = pl->pv_next;
1561 free_pventry(opv);
1562 }
1563 } else { /* read-only */
1564 do {
1565 int pr;
1566 pt = vaddrtopte(pv);
1567 if (pt == 0)
1568 continue;
1569 pr = ((vaddr_t)pt < ptemapstart ? PROT_KR : PROT_RO);
1570 pt[0].pg_prot = pr; pt[1].pg_prot = pr;
1571 pt[2].pg_prot = pr; pt[3].pg_prot = pr;
1572 pt[4].pg_prot = pr; pt[5].pg_prot = pr;
1573 pt[6].pg_prot = pr; pt[7].pg_prot = pr;
1574 } while ((pv = pv->pv_next));
1575 }
1576 PMAP_UNLOCK;
1577 #ifdef MULTIPROCESSOR
1578 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA);
1579 #endif
1580 mtpr(0, PR_TBIA);
1581 }
1582
1583 static void
pmap_remove_pcb(struct pmap * pm,struct pcb * thispcb)1584 pmap_remove_pcb(struct pmap *pm, struct pcb *thispcb)
1585 {
1586 struct pcb *pcb, **pcbp;
1587
1588 for (pcbp = &pm->pm_pcbs;
1589 (pcb = *pcbp) != NULL;
1590 pcbp = &pcb->pcb_pmnext) {
1591 #ifdef DIAGNOSTIC
1592 if (pcb->pcb_pm != pm)
1593 panic("pmap_remove_pcb: pcb %p (pm %p) not owned by pmap %p",
1594 pcb, pcb->pcb_pm, pm);
1595 #endif
1596 if (pcb == thispcb) {
1597 *pcbp = pcb->pcb_pmnext;
1598 thispcb->pcb_pm = NULL;
1599 return;
1600 }
1601 }
1602 #ifdef DIAGNOSTIC
1603 panic("pmap_remove_pcb: pmap %p: pcb %p not in list", pm, thispcb);
1604 #endif
1605 }
1606
1607 /*
1608 * Activate the address space for the specified process.
1609 * Note that if the process to activate is the current process, then
1610 * the processor internal registers must also be loaded; otherwise
1611 * the current process will have wrong pagetables.
1612 */
1613 void
pmap_activate(struct lwp * l)1614 pmap_activate(struct lwp *l)
1615 {
1616 struct pcb * const pcb = lwp_getpcb(l);
1617 struct pmap * const pmap = l->l_proc->p_vmspace->vm_map.pmap;
1618
1619 PMDEBUG(("pmap_activate: l %p\n", l));
1620
1621 pcb->P0BR = pmap->pm_p0br;
1622 pcb->P0LR = pmap->pm_p0lr|AST_PCB;
1623 pcb->P1BR = pmap->pm_p1br;
1624 pcb->P1LR = pmap->pm_p1lr;
1625
1626 if (pcb->pcb_pm != pmap) {
1627 if (pcb->pcb_pm != NULL)
1628 pmap_remove_pcb(pcb->pcb_pm, pcb);
1629 pcb->pcb_pmnext = pmap->pm_pcbs;
1630 pmap->pm_pcbs = pcb;
1631 pcb->pcb_pm = pmap;
1632 }
1633
1634 if (l == curlwp) {
1635 mtpr((uintptr_t)pmap->pm_p0br, PR_P0BR);
1636 mtpr(pmap->pm_p0lr|AST_PCB, PR_P0LR);
1637 mtpr((uintptr_t)pmap->pm_p1br, PR_P1BR);
1638 mtpr(pmap->pm_p1lr, PR_P1LR);
1639 mtpr(0, PR_TBIA);
1640 }
1641 }
1642
1643 void
pmap_deactivate(struct lwp * l)1644 pmap_deactivate(struct lwp *l)
1645 {
1646 struct pcb * const pcb = lwp_getpcb(l);
1647 struct pmap * const pmap = l->l_proc->p_vmspace->vm_map.pmap;
1648
1649 PMDEBUG(("pmap_deactivate: l %p\n", l));
1650
1651 if (pcb->pcb_pm == NULL)
1652 return;
1653 #ifdef DIAGNOSTIC
1654 if (pcb->pcb_pm != pmap)
1655 panic("pmap_deactivate: lwp %p pcb %p not owned by pmap %p",
1656 l, pcb, pmap);
1657 #endif
1658 pmap_remove_pcb(pmap, pcb);
1659 }
1660
1661 /*
1662 * removes the wired bit from a bunch of PTE's.
1663 */
1664 void
pmap_unwire(pmap_t pmap,vaddr_t v)1665 pmap_unwire(pmap_t pmap, vaddr_t v)
1666 {
1667 int *pte;
1668
1669 PMDEBUG(("pmap_unwire: pmap %p v %lx\n", pmap, v));
1670
1671 PMAP_LOCK;
1672 if (v & KERNBASE) {
1673 pte = (int *)kvtopte(v);
1674 } else {
1675 if (v < 0x40000000)
1676 pte = (int *)&pmap->pm_p0br[PG_PFNUM(v)];
1677 else
1678 pte = (int *)&pmap->pm_p1br[PG_PFNUM(v)];
1679 }
1680 pte[0] &= ~PG_W;
1681 pmap->pm_stats.wired_count--;
1682 PMAP_UNLOCK;
1683 }
1684
1685 /*
1686 * pv_entry functions.
1687 */
1688 struct pv_entry *pv_list;
1689
1690 /*
1691 * get_pventry().
1692 * The pv_table lock must be held before calling this.
1693 */
1694 struct pv_entry *
get_pventry(void)1695 get_pventry(void)
1696 {
1697 struct pv_entry *tmp;
1698
1699 if (pventries == 0)
1700 panic("get_pventry");
1701
1702 tmp = pv_list;
1703 pv_list = tmp->pv_next;
1704 pventries--;
1705 pvinuse++;
1706 return tmp;
1707 }
1708
1709 /*
1710 * free_pventry().
1711 * The pv_table lock must be held before calling this.
1712 */
1713 void
free_pventry(struct pv_entry * pv)1714 free_pventry(struct pv_entry *pv)
1715 {
1716 pv->pv_next = pv_list;
1717 pv_list = pv;
1718 pventries++;
1719 pvinuse--;
1720 }
1721
1722 /*
1723 * more_pventries().
1724 * The pmap_lock must be held before calling this.
1725 */
1726 void
more_pventries(void)1727 more_pventries(void)
1728 {
1729 struct pv_entry *pv;
1730 int i, count;
1731
1732 pv = (struct pv_entry *)getpage();
1733 if (pv == NULL)
1734 return;
1735 count = PAGE_SIZE/sizeof(struct pv_entry);
1736
1737 for (i = 0; i < count - 1; i++)
1738 pv[i].pv_next = &pv[i + 1];
1739
1740 pv[count - 1].pv_next = pv_list;
1741 pv_list = pv;
1742 pventries += count;
1743 }
1744
1745 static int *ptpp;
1746
1747 /*
1748 * Get a (vax-size) page, to use for page tables.
1749 */
1750 vaddr_t
get_ptp(void)1751 get_ptp(void)
1752 {
1753 int *a;
1754
1755 if ((a = ptpp)) {
1756 ptpp = (int *)*ptpp;
1757 memset(a, 0, VAX_NBPG);
1758 return (vaddr_t)a;
1759 }
1760 a = (int *)getpage();
1761 if (a != NULL) {
1762 a[128] = (int)&a[256];
1763 a[256] = (int)&a[384];
1764 a[384] = (int)&a[512];
1765 a[512] = (int)&a[640];
1766 a[640] = (int)&a[768];
1767 a[768] = (int)&a[896];
1768 a[896] = (int)ptpp;
1769 ptpp = &a[128];
1770 }
1771 return (vaddr_t)a;
1772 }
1773
1774 /*
1775 * Put a page table page on the free list.
1776 * The address v is in the direct-mapped area.
1777 */
1778 void
free_ptp(paddr_t v)1779 free_ptp(paddr_t v)
1780 {
1781 v |= KERNBASE;
1782 *(int *)v = (int)ptpp;
1783 ptpp = (int *)v;
1784 }
1785