3 #define _POSIX_SOURCE 1
5 #include <minix/callnr.h>
7 #include <minix/config.h>
8 #include <minix/const.h>
10 #include <minix/endpoint.h>
11 #include <minix/keymap.h>
12 #include <minix/minlib.h>
13 #include <minix/type.h>
14 #include <minix/ipc.h>
15 #include <minix/sysutil.h>
16 #include <minix/syslib.h>
17 #include <minix/safecopies.h>
18 #include <minix/cpufeature.h>
19 #include <minix/bitmap.h>
20 #include <minix/debug.h>
35 #include "sanitycheck.h"
37 static int vm_self_pages
;
39 /* PDE used to map in kernel, kernel physical address. */
40 static int pagedir_pde
= -1;
41 static u32_t global_bit
= 0, pagedir_pde_val
;
43 static multiboot_module_t
*kern_mb_mod
= NULL
;
44 static size_t kern_size
= 0;
45 static int kern_start_pde
= -1;
47 /* big page size available in hardware? */
48 static int bigpage_ok
= 1;
50 /* Our process table entry. */
51 struct vmproc
*vmprocess
= &vmproc
[VM_PROC_NR
];
53 /* Spare memory, ready to go after initialization, to avoid a
54 * circular dependency on allocating memory and writing it into VM's
58 #define SPAREPAGES 100
59 #define STATIC_SPAREPAGES 90
62 # define SPAREPAGES 80
63 # define STATIC_SPAREPAGES 75
65 # define SPAREPAGES 20
66 # define STATIC_SPAREPAGES 15
70 #define SPAREPAGEDIRS 11
71 #define STATIC_SPAREPAGEDIRS 10
73 int missing_sparedirs
= SPAREPAGEDIRS
;
77 } sparepagedirs
[SPAREPAGEDIRS
];
79 int missing_spares
= SPAREPAGES
;
83 } sparepages
[SPAREPAGES
];
86 #define is_staticaddr(v) ((vir_bytes) (v) < (vir_bytes) &_end)
88 #define MAX_KERNMAPPINGS 10
90 phys_bytes phys_addr
; /* Physical addr. */
91 phys_bytes len
; /* Length in bytes. */
92 vir_bytes vir_addr
; /* Offset in page table. */
94 } kern_mappings
[MAX_KERNMAPPINGS
];
97 /* Clicks must be pages, as
98 * - they must be page aligned to map them
99 * - they must be a multiple of the page size
100 * - it's inconvenient to have them bigger than pages, because we often want
102 * May as well require them to be equal then.
104 #if CLICK_SIZE != VM_PAGE_SIZE
105 #error CLICK_SIZE must be page size.
108 /* Page table that contains pointers to all page directories. */
109 phys_bytes page_directories_phys
;
110 u32_t
*page_directories
= NULL
;
112 static char static_sparepages
[VM_PAGE_SIZE
*STATIC_SPAREPAGES
]
113 __aligned(VM_PAGE_SIZE
);
116 static char static_sparepagedirs
[ARCH_PAGEDIR_SIZE
*STATIC_SPAREPAGEDIRS
+ ARCH_PAGEDIR_SIZE
] __aligned(ARCH_PAGEDIR_SIZE
);
120 /*===========================================================================*
122 *===========================================================================*/
123 void pt_sanitycheck(pt_t
*pt
, char *file
, int line
)
125 /* Basic pt sanity check. */
129 MYASSERT(pt
->pt_dir
);
130 MYASSERT(pt
->pt_dir_phys
);
132 for(slot
= 0; slot
< ELEMENTS(vmproc
); slot
++) {
133 if(pt
== &vmproc
[slot
].vm_pt
)
137 if(slot
>= ELEMENTS(vmproc
)) {
138 panic("pt_sanitycheck: passed pt not in any proc");
141 MYASSERT(usedpages_add(pt
->pt_dir_phys
, VM_PAGE_SIZE
) == OK
);
145 /*===========================================================================*
147 *===========================================================================*/
148 static u32_t
findhole(int pages
)
150 /* Find a space in the virtual address space of VM. */
152 int pde
= 0, try_restart
;
153 static u32_t lastv
= 0;
154 pt_t
*pt
= &vmprocess
->vm_pt
;
155 vir_bytes vmin
, vmax
;
160 vmin
= (vir_bytes
) (&_end
); /* marks end of VM BSS */
161 vmin
+= 1024*1024*1024; /* reserve 1GB virtual address space for VM heap */
162 vmin
&= ARCH_VM_ADDR_MASK
;
165 /* Input sanity check. */
166 assert(vmin
+ VM_PAGE_SIZE
>= vmin
);
167 assert(vmax
>= vmin
+ VM_PAGE_SIZE
);
168 assert((vmin
% VM_PAGE_SIZE
) == 0);
169 assert((vmax
% VM_PAGE_SIZE
) == 0);
175 if(curv
< vmin
|| curv
>= vmax
)
180 /* Start looking for a free page starting at vmin. */
187 assert(curv
>= vmin
);
190 #if defined(__i386__)
191 pde
= I386_VM_PDE(curv
);
192 pte
= I386_VM_PTE(curv
);
193 #elif defined(__arm__)
194 holev
= curv
; /* the candidate hole */
196 for (i
= 0; i
< pages
&& !nohole
; ++i
) {
202 #if defined(__i386__)
203 if(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
) ||
204 !(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PAGE_PRESENT
)) {
205 #elif defined(__arm__)
206 pde
= ARM_VM_PDE(curv
);
207 pte
= ARM_VM_PTE(curv
);
209 /* if page present, no hole */
210 if((pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
) &&
211 (pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_PRESENT
))
214 /* if not contiguous, no hole */
215 if (curv
!= holev
+ i
* VM_PAGE_SIZE
)
221 /* there's a large enough hole */
222 if (!nohole
&& i
== pages
) {
225 #if defined(__i386__)
227 #elif defined(__arm__)
232 #if defined(__i386__)
235 #elif defined(__arm__)
238 if(curv
>= vmax
&& try_restart
) {
244 printf("VM: out of virtual address space in vm\n");
249 /*===========================================================================*
251 *===========================================================================*/
252 void vm_freepages(vir_bytes vir
, int pages
)
254 assert(!(vir
% VM_PAGE_SIZE
));
256 if(is_staticaddr(vir
)) {
257 printf("VM: not freeing static page\n");
261 if(pt_writemap(vmprocess
, &vmprocess
->vm_pt
, vir
,
262 MAP_NONE
, pages
*VM_PAGE_SIZE
, 0,
263 WMF_OVERWRITE
| WMF_FREE
) != OK
)
264 panic("vm_freepages: pt_writemap failed");
269 /* If SANITYCHECKS are on, flush tlb so accessing freed pages is
270 * always trapped, also if not in tlb.
272 if((sys_vmctl(SELF
, VMCTL_FLUSHTLB
, 0)) != OK
) {
273 panic("VMCTL_FLUSHTLB failed");
278 /*===========================================================================*
280 *===========================================================================*/
281 static void *vm_getsparepage(phys_bytes
*phys
)
284 assert(missing_spares
>= 0 && missing_spares
<= SPAREPAGES
);
285 for(s
= 0; s
< SPAREPAGES
; s
++) {
286 if(sparepages
[s
].page
) {
288 sp
= sparepages
[s
].page
;
289 *phys
= sparepages
[s
].phys
;
290 sparepages
[s
].page
= NULL
;
292 assert(missing_spares
>= 0 && missing_spares
<= SPAREPAGES
);
296 printf("no spare found, %d missing\n", missing_spares
);
300 /*===========================================================================*
301 * vm_getsparepagedir *
302 *===========================================================================*/
303 static void *vm_getsparepagedir(phys_bytes
*phys
)
306 assert(missing_sparedirs
>= 0 && missing_sparedirs
<= SPAREPAGEDIRS
);
307 for(s
= 0; s
< SPAREPAGEDIRS
; s
++) {
308 if(sparepagedirs
[s
].pagedir
) {
310 sp
= sparepagedirs
[s
].pagedir
;
311 *phys
= sparepagedirs
[s
].phys
;
312 sparepagedirs
[s
].pagedir
= NULL
;
314 assert(missing_sparedirs
>= 0 && missing_sparedirs
<= SPAREPAGEDIRS
);
321 /*===========================================================================*
323 *===========================================================================*/
324 static void *vm_checkspares(void)
327 static int total
= 0, worst
= 0;
328 assert(missing_spares
>= 0 && missing_spares
<= SPAREPAGES
);
329 for(s
= 0; s
< SPAREPAGES
&& missing_spares
> 0; s
++) {
330 if(!sparepages
[s
].page
) {
332 if((sparepages
[s
].page
= vm_allocpage(&sparepages
[s
].phys
,
335 assert(missing_spares
>= 0);
336 assert(missing_spares
<= SPAREPAGES
);
338 printf("VM: warning: couldn't get new spare page\n");
342 if(worst
< n
) worst
= n
;
349 /*===========================================================================*
350 * vm_checksparedirs *
351 *===========================================================================*/
352 static void *vm_checksparedirs(void)
355 static int total
= 0, worst
= 0;
356 assert(missing_sparedirs
>= 0 && missing_sparedirs
<= SPAREPAGEDIRS
);
357 for(s
= 0; s
< SPAREPAGEDIRS
&& missing_sparedirs
> 0; s
++)
358 if(!sparepagedirs
[s
].pagedir
) {
360 if((sparepagedirs
[s
].pagedir
= vm_allocpage(&sparepagedirs
[s
].phys
,
363 assert(missing_sparedirs
>= 0);
364 assert(missing_sparedirs
<= SPAREPAGEDIRS
);
366 printf("VM: warning: couldn't get new spare pagedir\n");
369 if(worst
< n
) worst
= n
;
376 static int pt_init_done
;
378 /*===========================================================================*
380 *===========================================================================*/
381 void *vm_allocpages(phys_bytes
*phys
, int reason
, int pages
)
383 /* Allocate a page for use by VM itself. */
388 static int level
= 0;
392 pt
= &vmprocess
->vm_pt
;
393 assert(reason
>= 0 && reason
< VMP_CATEGORIES
);
402 if((level
> 1) || !pt_init_done
) {
405 if(pages
== 1) s
=vm_getsparepage(phys
);
406 else if(pages
== 4) s
=vm_getsparepagedir(phys
);
407 else panic("%d pages", pages
);
412 printf("VM: warning: out of spare pages\n");
414 if(!is_staticaddr(s
)) vm_self_pages
++;
419 if (reason
== VMP_PAGEDIR
) {
420 mem_flags
|= PAF_ALIGN16K
;
424 /* VM does have a pagetable, so get a page and map it in there.
425 * Where in our virtual address space can we put it?
427 loc
= findhole(pages
);
430 printf("VM: vm_allocpage: findhole failed\n");
434 /* Allocate page of memory for use by VM. As VM
435 * is trusted, we don't have to pre-clear it.
437 if((newpage
= alloc_mem(pages
, mem_flags
)) == NO_MEM
) {
439 printf("VM: vm_allocpage: alloc_mem failed\n");
443 *phys
= CLICK2ABS(newpage
);
445 /* Map this page into our address space. */
446 if((r
=pt_writemap(vmprocess
, pt
, loc
, *phys
, VM_PAGE_SIZE
*pages
,
447 ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_USER
| ARCH_VM_PTE_RW
449 | ARM_VM_PTE_WB
| ARM_VM_PTE_SHAREABLE
452 free_mem(newpage
, pages
);
453 printf("vm_allocpage writemap failed\n");
458 if((r
=sys_vmctl(SELF
, VMCTL_FLUSHTLB
, 0)) != OK
) {
459 panic("VMCTL_FLUSHTLB failed: %d", r
);
464 /* Return user-space-ready pointer to it. */
471 void *vm_allocpage(phys_bytes
*phys
, int reason
)
473 return vm_allocpages(phys
, reason
, 1);
476 /*===========================================================================*
478 *===========================================================================*/
479 void vm_pagelock(void *vir
, int lockflag
)
481 /* Mark a page allocated by vm_allocpage() unwritable, i.e. only for VM. */
482 vir_bytes m
= (vir_bytes
) vir
;
484 u32_t flags
= ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_USER
;
487 pt
= &vmprocess
->vm_pt
;
489 assert(!(m
% VM_PAGE_SIZE
));
492 flags
|= ARCH_VM_PTE_RW
;
495 flags
|= ARCH_VM_PTE_RO
;
496 flags
|= ARM_VM_PTE_WB
| ARM_VM_PTE_SHAREABLE
;
500 if((r
=pt_writemap(vmprocess
, pt
, m
, 0, VM_PAGE_SIZE
,
501 flags
, WMF_OVERWRITE
| WMF_WRITEFLAGSONLY
)) != OK
) {
502 panic("vm_lockpage: pt_writemap failed");
505 if((r
=sys_vmctl(SELF
, VMCTL_FLUSHTLB
, 0)) != OK
) {
506 panic("VMCTL_FLUSHTLB failed: %d", r
);
512 /*===========================================================================*
514 *===========================================================================*/
515 int vm_addrok(void *vir
, int writeflag
)
517 pt_t
*pt
= &vmprocess
->vm_pt
;
519 vir_bytes v
= (vir_bytes
) vir
;
521 #if defined(__i386__)
522 pde
= I386_VM_PDE(v
);
523 pte
= I386_VM_PTE(v
);
524 #elif defined(__arm__)
529 if(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
)) {
530 printf("addr not ok: missing pde %d\n", pde
);
534 #if defined(__i386__)
536 !(pt
->pt_dir
[pde
] & ARCH_VM_PTE_RW
)) {
537 printf("addr not ok: pde %d present but pde unwritable\n", pde
);
542 if(!(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_PRESENT
)) {
543 printf("addr not ok: missing pde %d / pte %d\n",
548 #if defined(__i386__)
550 !(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_RW
)) {
551 printf("addr not ok: pde %d / pte %d present but unwritable\n",
552 #elif defined(__arm__)
554 !(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_RO
)) {
555 printf("addr not ok: pde %d / pte %d present but writable\n",
564 /*===========================================================================*
566 *===========================================================================*/
567 static int pt_ptalloc(pt_t
*pt
, int pde
, u32_t flags
)
569 /* Allocate a page table and write its address into the page directory. */
573 /* Argument must make sense. */
574 assert(pde
>= 0 && pde
< ARCH_VM_DIR_ENTRIES
);
575 assert(!(flags
& ~(PTF_ALLFLAGS
)));
577 /* We don't expect to overwrite page directory entry, nor
578 * storage for the page table.
580 assert(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
));
581 assert(!pt
->pt_pt
[pde
]);
583 /* Get storage for the page table. */
584 if(!(pt
->pt_pt
[pde
] = vm_allocpage(&pt_phys
, VMP_PAGETABLE
)))
587 for(i
= 0; i
< ARCH_VM_PT_ENTRIES
; i
++)
588 pt
->pt_pt
[pde
][i
] = 0; /* Empty entry. */
590 /* Make page directory entry.
591 * The PDE is always 'present,' 'writable,' and 'user accessible,'
592 * relying on the PTE for protection.
594 #if defined(__i386__)
595 pt
->pt_dir
[pde
] = (pt_phys
& ARCH_VM_ADDR_MASK
) | flags
596 | ARCH_VM_PDE_PRESENT
| ARCH_VM_PTE_USER
| ARCH_VM_PTE_RW
;
597 #elif defined(__arm__)
598 pt
->pt_dir
[pde
] = (pt_phys
& ARCH_VM_PDE_MASK
)
599 | ARCH_VM_PDE_PRESENT
| ARM_VM_PDE_DOMAIN
;
605 /*===========================================================================*
606 * pt_ptalloc_in_range *
607 *===========================================================================*/
608 int pt_ptalloc_in_range(pt_t
*pt
, vir_bytes start
, vir_bytes end
,
609 u32_t flags
, int verify
)
611 /* Allocate all the page tables in the range specified. */
612 int pde
, first_pde
, last_pde
;
614 #if defined(__i386__)
615 first_pde
= I386_VM_PDE(start
);
616 last_pde
= I386_VM_PDE(end
-1);
617 #elif defined(__arm__)
618 first_pde
= ARM_VM_PDE(start
);
619 last_pde
= ARM_VM_PDE(end
-1);
621 assert(first_pde
>= 0);
622 assert(last_pde
< ARCH_VM_DIR_ENTRIES
);
624 /* Scan all page-directory entries in the range. */
625 for(pde
= first_pde
; pde
<= last_pde
; pde
++) {
626 assert(!(pt
->pt_dir
[pde
] & ARCH_VM_BIGPAGE
));
627 if(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
)) {
630 printf("pt_ptalloc_in_range: no pde %d\n", pde
);
633 assert(!pt
->pt_dir
[pde
]);
634 if((r
=pt_ptalloc(pt
, pde
, flags
)) != OK
) {
635 /* Couldn't do (complete) mapping.
636 * Don't bother freeing any previously
637 * allocated page tables, they're
638 * still writable, don't point to nonsense,
639 * and pt_ptalloc leaves the directory
640 * and other data in a consistent state.
644 assert(pt
->pt_pt
[pde
]);
646 assert(pt
->pt_pt
[pde
]);
647 assert(pt
->pt_dir
[pde
]);
648 assert(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
);
654 static char *ptestr(u32_t pte
)
656 #define FLAG(constant, name) { \
657 if(pte & (constant)) { strcat(str, name); strcat(str, " "); } \
661 if(!(pte
& ARCH_VM_PTE_PRESENT
)) {
662 return "not present";
665 #if defined(__i386__)
666 FLAG(ARCH_VM_PTE_RW
, "W");
667 #elif defined(__arm__)
668 if(pte
& ARCH_VM_PTE_RO
) {
674 FLAG(ARCH_VM_PTE_USER
, "U");
675 #if defined(__i386__)
676 FLAG(I386_VM_PWT
, "PWT");
677 FLAG(I386_VM_PCD
, "PCD");
678 FLAG(I386_VM_ACC
, "ACC");
679 FLAG(I386_VM_DIRTY
, "DIRTY");
680 FLAG(I386_VM_PS
, "PS");
681 FLAG(I386_VM_GLOBAL
, "G");
682 FLAG(I386_VM_PTAVAIL1
, "AV1");
683 FLAG(I386_VM_PTAVAIL2
, "AV2");
684 FLAG(I386_VM_PTAVAIL3
, "AV3");
685 #elif defined(__arm__)
686 FLAG(ARM_VM_PTE_SUPER
, "S");
687 FLAG(ARM_VM_PTE_SHAREABLE
, "SH");
688 FLAG(ARM_VM_PTE_WB
, "WB");
689 FLAG(ARM_VM_PTE_WT
, "WT");
695 /*===========================================================================*
697 *===========================================================================*/
698 int pt_map_in_range(struct vmproc
*src_vmp
, struct vmproc
*dst_vmp
,
699 vir_bytes start
, vir_bytes end
)
701 /* Transfer all the mappings from the pt of the source process to the pt of
702 * the destination process in the range specified.
708 pt
= &src_vmp
->vm_pt
;
709 dst_pt
= &dst_vmp
->vm_pt
;
711 end
= end
? end
: VM_DATATOP
;
712 assert(start
% VM_PAGE_SIZE
== 0);
713 assert(end
% VM_PAGE_SIZE
== 0);
714 #if defined(__i386__)
715 assert(start
<= end
);
716 assert(I386_VM_PDE(end
) < ARCH_VM_DIR_ENTRIES
);
717 #elif defined(__arm__)
718 assert(ARM_VM_PDE(start
) >= 0 && start
<= end
);
719 assert(ARM_VM_PDE(end
) < ARCH_VM_DIR_ENTRIES
);
723 printf("VM: pt_map_in_range: src = %d, dst = %d\n",
724 src_vmp
->vm_endpoint
, dst_vmp
->vm_endpoint
);
725 printf("VM: pt_map_in_range: transferring from 0x%08x (pde %d pte %d) to 0x%08x (pde %d pte %d)\n",
726 #if defined(__i386__)
727 start
, I386_VM_PDE(start
), I386_VM_PTE(start
),
728 end
, I386_VM_PDE(end
), I386_VM_PTE(end
));
729 #elif defined(__arm__)
730 start
, ARM_VM_PDE(start
), ARM_VM_PTE(start
),
731 end
, ARM_VM_PDE(end
), ARM_VM_PTE(end
));
735 /* Scan all page-table entries in the range. */
736 for(viraddr
= start
; viraddr
<= end
; viraddr
+= VM_PAGE_SIZE
) {
737 #if defined(__i386__)
738 pde
= I386_VM_PDE(viraddr
);
739 #elif defined(__arm__)
740 pde
= ARM_VM_PDE(viraddr
);
742 if(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
)) {
743 if(viraddr
== VM_DATATOP
) break;
746 #if defined(__i386__)
747 pte
= I386_VM_PTE(viraddr
);
748 #elif defined(__arm__)
749 pte
= ARM_VM_PTE(viraddr
);
751 if(!(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_PRESENT
)) {
752 if(viraddr
== VM_DATATOP
) break;
756 /* Transfer the mapping. */
757 dst_pt
->pt_pt
[pde
][pte
] = pt
->pt_pt
[pde
][pte
];
759 if(viraddr
== VM_DATATOP
) break;
765 /*===========================================================================*
767 *===========================================================================*/
768 int pt_ptmap(struct vmproc
*src_vmp
, struct vmproc
*dst_vmp
)
770 /* Transfer mappings to page dir and page tables from source process and
771 * destination process. Make sure all the mappings are above the stack, not
772 * to corrupt valid mappings in the data segment of the destination process.
779 pt
= &src_vmp
->vm_pt
;
782 printf("VM: pt_ptmap: src = %d, dst = %d\n",
783 src_vmp
->vm_endpoint
, dst_vmp
->vm_endpoint
);
786 /* Transfer mapping to the page directory. */
787 viraddr
= (vir_bytes
) pt
->pt_dir
;
788 physaddr
= pt
->pt_dir_phys
& ARCH_VM_ADDR_MASK
;
789 #if defined(__i386__)
790 if((r
=pt_writemap(dst_vmp
, &dst_vmp
->vm_pt
, viraddr
, physaddr
, VM_PAGE_SIZE
,
791 ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_USER
| ARCH_VM_PTE_RW
,
792 #elif defined(__arm__)
793 if((r
=pt_writemap(dst_vmp
, &dst_vmp
->vm_pt
, viraddr
, physaddr
, ARCH_PAGEDIR_SIZE
,
794 ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_USER
| ARCH_VM_PTE_RW
|
795 ARM_VM_PTE_WB
| ARM_VM_PTE_SHAREABLE
,
797 WMF_OVERWRITE
)) != OK
) {
801 printf("VM: pt_ptmap: transferred mapping to page dir: 0x%08x (0x%08x)\n",
805 /* Scan all non-reserved page-directory entries. */
806 for(pde
=0; pde
< ARCH_VM_DIR_ENTRIES
; pde
++) {
807 if(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
)) {
811 /* Transfer mapping to the page table. */
812 viraddr
= (vir_bytes
) pt
->pt_pt
[pde
];
813 #if defined(__i386__)
814 physaddr
= pt
->pt_dir
[pde
] & ARCH_VM_ADDR_MASK
;
815 #elif defined(__arm__)
816 physaddr
= pt
->pt_dir
[pde
] & ARCH_VM_PDE_MASK
;
818 if((r
=pt_writemap(dst_vmp
, &dst_vmp
->vm_pt
, viraddr
, physaddr
, VM_PAGE_SIZE
,
819 ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_USER
| ARCH_VM_PTE_RW
821 | ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_USER
| ARCH_VM_PTE_RW
|
822 ARM_VM_PTE_WB
| ARM_VM_PTE_SHAREABLE
825 WMF_OVERWRITE
)) != OK
) {
833 void pt_clearmapcache(void)
835 /* Make sure kernel will invalidate tlb when using current
836 * pagetable (i.e. vm's) to make new mappings before new cr3
839 if(sys_vmctl(SELF
, VMCTL_CLEARMAPCACHE
, 0) != OK
)
840 panic("VMCTL_CLEARMAPCACHE failed");
843 /*===========================================================================*
845 *===========================================================================*/
846 int pt_writemap(struct vmproc
* vmp
,
854 /* Write mapping into page table. Allocate a new page table if necessary. */
855 /* Page directory and table entries for this virtual address. */
861 int vminhibit_clear
= 0;
863 * don't do it everytime, stop the process only on the first change and
864 * resume the execution on the last change. Do in a wrapper of this
867 if (vmp
&& vmp
->vm_endpoint
!= NONE
&& vmp
->vm_endpoint
!= VM_PROC_NR
&&
868 !(vmp
->vm_flags
& VMF_EXITING
)) {
869 sys_vmctl(vmp
->vm_endpoint
, VMCTL_VMINHIBIT_SET
, 0);
874 if(writemapflags
& WMF_VERIFY
)
877 assert(!(bytes
% VM_PAGE_SIZE
));
878 assert(!(flags
& ~(PTF_ALLFLAGS
)));
880 pages
= bytes
/ VM_PAGE_SIZE
;
882 /* MAP_NONE means to clear the mapping. It doesn't matter
883 * what's actually written into the PTE if PRESENT
884 * isn't on, so we can just write MAP_NONE into it.
886 assert(physaddr
== MAP_NONE
|| (flags
& ARCH_VM_PTE_PRESENT
));
887 assert(physaddr
!= MAP_NONE
|| !flags
);
889 /* First make sure all the necessary page tables are allocated,
890 * before we start writing in any of them, because it's a pain
891 * to undo our work properly.
893 ret
= pt_ptalloc_in_range(pt
, v
, v
+ VM_PAGE_SIZE
*pages
, flags
, verify
);
895 printf("VM: writemap: pt_ptalloc_in_range failed\n");
899 /* Now write in them. */
900 for(p
= 0; p
< pages
; p
++) {
902 #if defined(__i386__)
903 int pde
= I386_VM_PDE(v
);
904 int pte
= I386_VM_PTE(v
);
905 #elif defined(__arm__)
906 int pde
= ARM_VM_PDE(v
);
907 int pte
= ARM_VM_PTE(v
);
910 assert(!(v
% VM_PAGE_SIZE
));
911 assert(pte
>= 0 && pte
< ARCH_VM_PT_ENTRIES
);
912 assert(pde
>= 0 && pde
< ARCH_VM_DIR_ENTRIES
);
914 /* Page table has to be there. */
915 assert(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
);
917 /* We do not expect it to be a bigpage. */
918 assert(!(pt
->pt_dir
[pde
] & ARCH_VM_BIGPAGE
));
920 /* Make sure page directory entry for this page table
921 * is marked present and page table entry is available.
923 assert(pt
->pt_pt
[pde
]);
926 /* We don't expect to overwrite a page. */
927 if(!(writemapflags
& (WMF_OVERWRITE
|WMF_VERIFY
)))
928 assert(!(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_PRESENT
));
930 if(writemapflags
& (WMF_WRITEFLAGSONLY
|WMF_FREE
)) {
931 #if defined(__i386__)
932 physaddr
= pt
->pt_pt
[pde
][pte
] & ARCH_VM_ADDR_MASK
;
933 #elif defined(__arm__)
934 physaddr
= pt
->pt_pt
[pde
][pte
] & ARM_VM_PTE_MASK
;
938 if(writemapflags
& WMF_FREE
) {
939 free_mem(ABS2CLICK(physaddr
), 1);
942 /* Entry we will write. */
943 #if defined(__i386__)
944 entry
= (physaddr
& ARCH_VM_ADDR_MASK
) | flags
;
945 #elif defined(__arm__)
946 entry
= (physaddr
& ARM_VM_PTE_MASK
) | flags
;
951 maskedentry
= pt
->pt_pt
[pde
][pte
];
952 #if defined(__i386__)
953 maskedentry
&= ~(I386_VM_ACC
|I386_VM_DIRTY
);
955 /* Verify pagetable entry. */
956 #if defined(__i386__)
957 if(entry
& ARCH_VM_PTE_RW
) {
958 /* If we expect a writable page, allow a readonly page. */
959 maskedentry
|= ARCH_VM_PTE_RW
;
961 #elif defined(__arm__)
962 if(!(entry
& ARCH_VM_PTE_RO
)) {
963 /* If we expect a writable page, allow a readonly page. */
964 maskedentry
&= ~ARCH_VM_PTE_RO
;
967 if(maskedentry
!= entry
) {
968 printf("pt_writemap: mismatch: ");
969 #if defined(__i386__)
970 if((entry
& ARCH_VM_ADDR_MASK
) !=
971 (maskedentry
& ARCH_VM_ADDR_MASK
)) {
972 #elif defined(__arm__)
973 if((entry
& ARM_VM_PTE_MASK
) !=
974 (maskedentry
& ARM_VM_PTE_MASK
)) {
976 printf("pt_writemap: physaddr mismatch (0x%lx, 0x%lx); ",
977 (long)entry
, (long)maskedentry
);
978 } else printf("phys ok; ");
979 printf(" flags: found %s; ",
980 ptestr(pt
->pt_pt
[pde
][pte
]));
981 printf(" masked %s; ",
982 ptestr(maskedentry
));
983 printf(" expected %s\n", ptestr(entry
));
984 printf("found 0x%x, wanted 0x%x\n",
985 pt
->pt_pt
[pde
][pte
], entry
);
990 /* Write pagetable entry. */
991 pt
->pt_pt
[pde
][pte
] = entry
;
994 physaddr
+= VM_PAGE_SIZE
;
1001 if (vminhibit_clear
) {
1002 assert(vmp
&& vmp
->vm_endpoint
!= NONE
&& vmp
->vm_endpoint
!= VM_PROC_NR
&&
1003 !(vmp
->vm_flags
& VMF_EXITING
));
1004 sys_vmctl(vmp
->vm_endpoint
, VMCTL_VMINHIBIT_CLEAR
, 0);
1011 /*===========================================================================*
1013 *===========================================================================*/
1014 int pt_checkrange(pt_t
*pt
, vir_bytes v
, size_t bytes
,
1019 assert(!(bytes
% VM_PAGE_SIZE
));
1021 pages
= bytes
/ VM_PAGE_SIZE
;
1023 for(p
= 0; p
< pages
; p
++) {
1024 #if defined(__i386__)
1025 int pde
= I386_VM_PDE(v
);
1026 int pte
= I386_VM_PTE(v
);
1027 #elif defined(__arm__)
1028 int pde
= ARM_VM_PDE(v
);
1029 int pte
= ARM_VM_PTE(v
);
1032 assert(!(v
% VM_PAGE_SIZE
));
1033 assert(pte
>= 0 && pte
< ARCH_VM_PT_ENTRIES
);
1034 assert(pde
>= 0 && pde
< ARCH_VM_DIR_ENTRIES
);
1036 /* Page table has to be there. */
1037 if(!(pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
))
1040 /* Make sure page directory entry for this page table
1041 * is marked present and page table entry is available.
1043 assert((pt
->pt_dir
[pde
] & ARCH_VM_PDE_PRESENT
) && pt
->pt_pt
[pde
]);
1045 if(!(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_PRESENT
)) {
1049 #if defined(__i386__)
1050 if(write
&& !(pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_RW
)) {
1051 #elif defined(__arm__)
1052 if(write
&& (pt
->pt_pt
[pde
][pte
] & ARCH_VM_PTE_RO
)) {
1063 /*===========================================================================*
1065 *===========================================================================*/
1066 int pt_new(pt_t
*pt
)
1068 /* Allocate a pagetable root. Allocate a page-aligned page directory
1069 * and set them to 0 (indicating no page tables are allocated). Lookup
1070 * its physical address as we'll need that in the future. Verify it's
1075 /* Don't ever re-allocate/re-move a certain process slot's
1076 * page directory once it's been created. This is a fraction
1077 * faster, but also avoids having to invalidate the page
1078 * mappings from in-kernel page tables pointing to
1079 * the page directories (the page_directories data).
1082 !(pt
->pt_dir
= vm_allocpages((phys_bytes
*)&pt
->pt_dir_phys
,
1083 VMP_PAGEDIR
, ARCH_PAGEDIR_SIZE
/VM_PAGE_SIZE
))) {
1087 assert(!((u32_t
)pt
->pt_dir_phys
% ARCH_PAGEDIR_SIZE
));
1089 for(i
= 0; i
< ARCH_VM_DIR_ENTRIES
; i
++) {
1090 pt
->pt_dir
[i
] = 0; /* invalid entry (PRESENT bit = 0) */
1091 pt
->pt_pt
[i
] = NULL
;
1094 /* Where to start looking for free virtual address space? */
1097 /* Map in kernel. */
1098 if((r
=pt_mapkernel(pt
)) != OK
)
1104 static int freepde(void)
1106 int p
= kernel_boot_info
.freepde_start
++;
1107 assert(kernel_boot_info
.freepde_start
< ARCH_VM_DIR_ENTRIES
);
1111 /*===========================================================================*
1113 *===========================================================================*/
1118 int global_bit_ok
= 0;
1119 vir_bytes sparepages_mem
;
1120 #if defined(__arm__)
1121 vir_bytes sparepagedirs_mem
;
1123 static u32_t currentpagedir
[ARCH_VM_DIR_ENTRIES
];
1124 int m
= kernel_boot_info
.kern_mod
;
1125 #if defined(__i386__)
1126 u32_t mypdbr
; /* Page Directory Base Register (cr3) value */
1127 #elif defined(__arm__)
1131 /* Find what the physical location of the kernel is. */
1133 assert(m
< kernel_boot_info
.mods_with_kernel
);
1134 assert(kernel_boot_info
.mods_with_kernel
< MULTIBOOT_MAX_MODS
);
1135 kern_mb_mod
= &kernel_boot_info
.module_list
[m
];
1136 kern_size
= kern_mb_mod
->mod_end
- kern_mb_mod
->mod_start
;
1137 assert(!(kern_mb_mod
->mod_start
% ARCH_BIG_PAGE_SIZE
));
1138 assert(!(kernel_boot_info
.vir_kern_start
% ARCH_BIG_PAGE_SIZE
));
1139 kern_start_pde
= kernel_boot_info
.vir_kern_start
/ ARCH_BIG_PAGE_SIZE
;
1141 /* Get ourselves spare pages. */
1142 sparepages_mem
= (vir_bytes
) static_sparepages
;
1143 assert(!(sparepages_mem
% VM_PAGE_SIZE
));
1145 #if defined(__arm__)
1146 /* Get ourselves spare pagedirs. */
1147 sparepagedirs_mem
= (vir_bytes
) static_sparepagedirs
;
1148 assert(!(sparepagedirs_mem
% ARCH_PAGEDIR_SIZE
));
1151 /* Spare pages are used to allocate memory before VM has its own page
1152 * table that things (i.e. arbitrary physical memory) can be mapped into.
1153 * We get it by pre-allocating it in our bss (allocated and mapped in by
1154 * the kernel) in static_sparepages. We also need the physical addresses
1155 * though; we look them up now so they are ready for use.
1157 #if defined(__arm__)
1158 missing_sparedirs
= 0;
1159 assert(STATIC_SPAREPAGEDIRS
< SPAREPAGEDIRS
);
1160 for(s
= 0; s
< SPAREPAGEDIRS
; s
++) {
1161 vir_bytes v
= (sparepagedirs_mem
+ s
*ARCH_PAGEDIR_SIZE
);;
1163 if((r
=sys_umap(SELF
, VM_D
, (vir_bytes
) v
,
1164 ARCH_PAGEDIR_SIZE
, &ph
)) != OK
)
1165 panic("pt_init: sys_umap failed: %d", r
);
1166 if(s
>= STATIC_SPAREPAGEDIRS
) {
1167 sparepagedirs
[s
].pagedir
= NULL
;
1168 missing_sparedirs
++;
1171 sparepagedirs
[s
].pagedir
= (void *) v
;
1172 sparepagedirs
[s
].phys
= ph
;
1177 assert(STATIC_SPAREPAGES
< SPAREPAGES
);
1178 for(s
= 0; s
< SPAREPAGES
; s
++) {
1179 vir_bytes v
= (sparepages_mem
+ s
*VM_PAGE_SIZE
);;
1181 if((r
=sys_umap(SELF
, VM_D
, (vir_bytes
) v
,
1182 VM_PAGE_SIZE
*SPAREPAGES
, &ph
)) != OK
)
1183 panic("pt_init: sys_umap failed: %d", r
);
1184 if(s
>= STATIC_SPAREPAGES
) {
1185 sparepages
[s
].page
= NULL
;
1189 sparepages
[s
].page
= (void *) v
;
1190 sparepages
[s
].phys
= ph
;
1193 #if defined(__i386__)
1194 /* global bit and 4MB pages available? */
1195 global_bit_ok
= _cpufeature(_CPUF_I386_PGE
);
1196 bigpage_ok
= _cpufeature(_CPUF_I386_PSE
);
1198 /* Set bit for PTE's and PDE's if available. */
1200 global_bit
= I386_VM_GLOBAL
;
1203 /* Allocate us a page table in which to remember page directory
1206 if(!(page_directories
= vm_allocpage(&page_directories_phys
,
1208 panic("no virt addr for vm mappings");
1210 memset(page_directories
, 0, VM_PAGE_SIZE
);
1212 /* Now reserve another pde for kernel's own mappings. */
1215 phys_bytes addr
, len
;
1216 int flags
, index
= 0;
1219 kernmap_pde
= freepde();
1220 offset
= kernmap_pde
* ARCH_BIG_PAGE_SIZE
;
1222 while(sys_vmctl_get_mapping(index
, &addr
, &len
,
1226 if(index
>= MAX_KERNMAPPINGS
)
1227 panic("VM: too many kernel mappings: %d", index
);
1228 kern_mappings
[index
].phys_addr
= addr
;
1229 kern_mappings
[index
].len
= len
;
1230 kern_mappings
[index
].flags
= flags
;
1231 kern_mappings
[index
].vir_addr
= offset
;
1232 kern_mappings
[index
].flags
=
1233 ARCH_VM_PTE_PRESENT
;
1234 if(flags
& VMMF_UNCACHED
)
1235 #if defined(__i386__)
1236 kern_mappings
[index
].flags
|= PTF_NOCACHE
;
1237 #elif defined(__arm__)
1238 kern_mappings
[index
].flags
|= ARM_VM_PTE_DEVICE
;
1240 kern_mappings
[index
].flags
|=
1241 ARM_VM_PTE_WB
| ARM_VM_PTE_SHAREABLE
;
1243 if(flags
& VMMF_USER
)
1244 kern_mappings
[index
].flags
|= ARCH_VM_PTE_USER
;
1245 #if defined(__arm__)
1247 kern_mappings
[index
].flags
|= ARM_VM_PTE_SUPER
;
1249 if(flags
& VMMF_WRITE
)
1250 kern_mappings
[index
].flags
|= ARCH_VM_PTE_RW
;
1251 #if defined(__i386__)
1252 if(flags
& VMMF_GLO
)
1253 kern_mappings
[index
].flags
|= I386_VM_GLOBAL
;
1254 #elif defined(__arm__)
1256 kern_mappings
[index
].flags
|= ARCH_VM_PTE_RO
;
1258 if(addr
% VM_PAGE_SIZE
)
1259 panic("VM: addr unaligned: %d", addr
);
1260 if(len
% VM_PAGE_SIZE
)
1261 panic("VM: len unaligned: %d", len
);
1263 if(sys_vmctl_reply_mapping(index
, vir
) != OK
)
1264 panic("VM: reply failed");
1269 #if defined(__i386__)
1270 usedpde
= I386_VM_PDE(offset
);
1271 #elif defined(__arm__)
1272 usedpde
= ARM_VM_PDE(offset
);
1274 while(usedpde
> kernmap_pde
) {
1275 int newpde
= freepde();
1276 assert(newpde
== kernmap_pde
+1);
1277 kernmap_pde
= newpde
;
1282 /* Find a PDE below processes available for mapping in the
1285 pagedir_pde
= freepde();
1286 #if defined(__i386__)
1287 pagedir_pde_val
= (page_directories_phys
& ARCH_VM_ADDR_MASK
) |
1288 ARCH_VM_PDE_PRESENT
| ARCH_VM_PTE_RW
;
1289 #elif defined(__arm__)
1290 pagedir_pde_val
= (page_directories_phys
& ARCH_VM_PDE_MASK
) |
1291 ARCH_VM_PDE_PRESENT
| ARM_VM_PDE_DOMAIN
;
1294 /* Allright. Now. We have to make our own page directory and page tables,
1295 * that the kernel has already set up, accessible to us. It's easier to
1296 * understand if we just copy all the required pages (i.e. page directory
1297 * and page tables), and set up the pointers as if VM had done it itself.
1299 * This allocation will happen without using any page table, and just
1302 newpt
= &vmprocess
->vm_pt
;
1303 if(pt_new(newpt
) != OK
)
1304 panic("vm pt_new failed");
1306 /* Get our current pagedir so we can see it. */
1307 #if defined(__i386__)
1308 if(sys_vmctl_get_pdbr(SELF
, &mypdbr
) != OK
)
1309 #elif defined(__arm__)
1310 if(sys_vmctl_get_pdbr(SELF
, &myttbr
) != OK
)
1312 panic("VM: sys_vmctl_get_pdbr failed");
1313 #if defined(__i386__)
1314 if(sys_vircopy(NONE
, mypdbr
, SELF
,
1315 (vir_bytes
) currentpagedir
, VM_PAGE_SIZE
) != OK
)
1316 #elif defined(__arm__)
1317 if(sys_vircopy(NONE
, myttbr
, SELF
,
1318 (vir_bytes
) currentpagedir
, ARCH_PAGEDIR_SIZE
) != OK
)
1320 panic("VM: sys_vircopy failed");
1322 /* We have mapped in kernel ourselves; now copy mappings for VM
1323 * that kernel made, including allocations for BSS. Skip identity
1324 * mapping bits; just map in VM.
1326 for(p
= 0; p
< ARCH_VM_DIR_ENTRIES
; p
++) {
1327 u32_t entry
= currentpagedir
[p
];
1328 phys_bytes ptaddr_kern
, ptaddr_us
;
1330 /* BIGPAGEs are kernel mapping (do ourselves) or boot
1331 * identity mapping (don't want).
1333 if(!(entry
& ARCH_VM_PDE_PRESENT
)) continue;
1334 if((entry
& ARCH_VM_BIGPAGE
)) continue;
1336 if(pt_ptalloc(newpt
, p
, 0) != OK
)
1337 panic("pt_ptalloc failed");
1338 assert(newpt
->pt_dir
[p
] & ARCH_VM_PDE_PRESENT
);
1340 #if defined(__i386__)
1341 ptaddr_kern
= entry
& ARCH_VM_ADDR_MASK
;
1342 ptaddr_us
= newpt
->pt_dir
[p
] & ARCH_VM_ADDR_MASK
;
1343 #elif defined(__arm__)
1344 ptaddr_kern
= entry
& ARCH_VM_PDE_MASK
;
1345 ptaddr_us
= newpt
->pt_dir
[p
] & ARCH_VM_PDE_MASK
;
1348 /* Copy kernel-initialized pagetable contents into our
1349 * normally accessible pagetable.
1351 if(sys_abscopy(ptaddr_kern
, ptaddr_us
, VM_PAGE_SIZE
) != OK
)
1352 panic("pt_init: abscopy failed");
1355 /* Inform kernel vm has a newly built page table. */
1356 assert(vmproc
[VM_PROC_NR
].vm_endpoint
== VM_PROC_NR
);
1357 pt_bind(newpt
, &vmproc
[VM_PROC_NR
]);
1367 /*===========================================================================*
1369 *===========================================================================*/
1370 int pt_bind(pt_t
*pt
, struct vmproc
*who
)
1375 int pages_per_pagedir
= ARCH_PAGEDIR_SIZE
/VM_PAGE_SIZE
;
1377 /* Basic sanity checks. */
1379 assert(who
->vm_flags
& VMF_INUSE
);
1382 assert(pagedir_pde
>= 0);
1384 slot
= who
->vm_slot
;
1386 assert(slot
< ELEMENTS(vmproc
));
1387 assert(slot
< ARCH_VM_PT_ENTRIES
/ pages_per_pagedir
);
1389 #if defined(__i386__)
1390 phys
= pt
->pt_dir_phys
& ARCH_VM_ADDR_MASK
;
1391 #elif defined(__arm__)
1392 phys
= pt
->pt_dir_phys
& ARM_VM_PTE_MASK
;
1394 assert(pt
->pt_dir_phys
== phys
);
1395 assert(!(pt
->pt_dir_phys
% ARCH_PAGEDIR_SIZE
));
1397 /* Update "page directory pagetable." */
1398 #if defined(__i386__)
1399 page_directories
[slot
] = phys
| ARCH_VM_PDE_PRESENT
|ARCH_VM_PTE_RW
;
1400 #elif defined(__arm__)
1403 for (i
= 0; i
< pages_per_pagedir
; i
++)
1404 page_directories
[slot
*pages_per_pagedir
+i
] =
1405 (phys
+i
*VM_PAGE_SIZE
) |
1406 ARCH_VM_PTE_PRESENT
| ARCH_VM_PTE_RW
|
1411 /* This is where the PDE's will be visible to the kernel
1412 * in its address space.
1414 pdes
= (void *) (pagedir_pde
*ARCH_BIG_PAGE_SIZE
+
1415 #if defined(__i386__)
1416 slot
* VM_PAGE_SIZE
);
1417 #elif defined(__arm__)
1418 slot
* ARCH_PAGEDIR_SIZE
);
1422 printf("VM: slot %d endpoint %d has pde val 0x%lx at kernel address 0x%lx\n",
1423 slot
, who
->vm_endpoint
, page_directories
[slot
], pdes
);
1425 /* Tell kernel about new page table root. */
1426 return sys_vmctl_set_addrspace(who
->vm_endpoint
, pt
->pt_dir_phys
, pdes
);
1429 /*===========================================================================*
1431 *===========================================================================*/
1432 void pt_free(pt_t
*pt
)
1434 /* Free memory associated with this pagetable. */
1437 for(i
= 0; i
< ARCH_VM_DIR_ENTRIES
; i
++)
1439 vm_freepages((vir_bytes
) pt
->pt_pt
[i
], 1);
1444 /*===========================================================================*
1446 *===========================================================================*/
1447 int pt_mapkernel(pt_t
*pt
)
1450 int kern_pde
= kern_start_pde
;
1451 phys_bytes addr
, mapped
= 0;
1453 /* Any page table needs to map in the kernel address space. */
1455 assert(pagedir_pde
>= 0);
1456 assert(kern_pde
>= 0);
1458 /* pt_init() has made sure this is ok. */
1459 addr
= kern_mb_mod
->mod_start
;
1461 /* Actually mapping in kernel */
1462 while(mapped
< kern_size
) {
1463 #if defined(__i386__)
1464 pt
->pt_dir
[kern_pde
] = addr
| ARCH_VM_PDE_PRESENT
|
1465 ARCH_VM_BIGPAGE
| ARCH_VM_PTE_RW
| global_bit
;
1466 #elif defined(__arm__)
1467 pt
->pt_dir
[kern_pde
] = (addr
& ARCH_VM_PDE_MASK
) |
1469 ARM_VM_SECTION_DOMAIN
| ARM_VM_SECTION_WB
|
1470 ARM_VM_SECTION_SHAREABLE
| ARM_VM_SECTION_SUPER
;
1473 mapped
+= ARCH_BIG_PAGE_SIZE
;
1474 addr
+= ARCH_BIG_PAGE_SIZE
;
1477 /* Kernel also wants to know about all page directories. */
1478 assert(pagedir_pde
> kern_pde
);
1479 pt
->pt_dir
[pagedir_pde
] = pagedir_pde_val
;
1481 /* Kernel also wants various mappings of its own. */
1482 for(i
= 0; i
< kernmappings
; i
++) {
1484 if((r
=pt_writemap(NULL
, pt
,
1485 kern_mappings
[i
].vir_addr
,
1486 kern_mappings
[i
].phys_addr
,
1487 kern_mappings
[i
].len
,
1488 kern_mappings
[i
].flags
, 0)) != OK
) {
1492 #if defined(__arm__)
1493 if(kern_mappings
[i
].phys_addr
== 0x48000000) {
1494 if((r
=pt_writemap(NULL
, pt
,
1495 kern_mappings
[i
].phys_addr
,
1496 kern_mappings
[i
].phys_addr
,
1497 kern_mappings
[i
].len
,
1498 kern_mappings
[i
].flags
, 0)) != OK
) {
1508 /*===========================================================================*
1510 *===========================================================================*/
1514 #if defined(__arm__)
1515 vm_checksparedirs();
1519 int get_vm_self_pages(void) { return vm_self_pages
; }