diff --git a/minix/servers/vm/pagetable.c b/minix/servers/vm/pagetable.c index e7885bc64..66dd9da0f 100644 --- a/minix/servers/vm/pagetable.c +++ b/minix/servers/vm/pagetable.c @@ -113,6 +113,17 @@ static char static_sparepages[VM_PAGE_SIZE*STATIC_SPAREPAGES] static char static_sparepagedirs[ARCH_PAGEDIR_SIZE*STATIC_SPAREPAGEDIRS + ARCH_PAGEDIR_SIZE] __aligned(ARCH_PAGEDIR_SIZE); #endif +void pt_assert(pt_t *pt) +{ + char dir[4096]; + pt_clearmapcache(); + if((sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) { + panic("VMCTL_FLUSHTLB failed"); + } + sys_physcopy(NONE, pt->pt_dir_phys, SELF, (vir_bytes) dir, sizeof(dir), 0); + assert(!memcmp(dir, pt->pt_dir, sizeof(dir))); +} + #if SANITYCHECKS /*===========================================================================* * pt_sanitycheck * @@ -255,7 +266,6 @@ static void *vm_getsparepage(phys_bytes *phys) { void *ptr; if(reservedqueue_alloc(spare_pagequeue, phys, &ptr) != OK) { - printf("vm_getsparepage: no spare found\n"); return NULL; } assert(ptr); @@ -662,6 +672,7 @@ int pt_map_in_range(struct vmproc *src_vmp, struct vmproc *dst_vmp, /* Transfer the mapping. */ dst_pt->pt_pt[pde][pte] = pt->pt_pt[pde][pte]; + assert(dst_pt->pt_pt[pde]); if(viraddr == VM_DATATOP) break; } @@ -709,11 +720,13 @@ int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp) #endif /* Scan all non-reserved page-directory entries. */ - for(pde=0; pde < ARCH_VM_DIR_ENTRIES; pde++) { + for(pde=0; pde < kern_start_pde; pde++) { if(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT)) { continue; } + if(!pt->pt_pt[pde]) { panic("pde %d empty\n", pde); } + /* Transfer mapping to the page table. */ viraddr = (vir_bytes) pt->pt_pt[pde]; #if defined(__i386__) @@ -721,6 +734,7 @@ int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp) #elif defined(__arm__) physaddr = pt->pt_dir[pde] & ARCH_VM_PDE_MASK; #endif + assert(viraddr); if((r=pt_writemap(dst_vmp, &dst_vmp->vm_pt, viraddr, physaddr, VM_PAGE_SIZE, ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW #ifdef __arm__ @@ -1024,6 +1038,40 @@ static int freepde(void) return p; } +void pt_allocate_kernel_mapped_pagetables(void) +{ + /* Reserve PDEs available for mapping in the page directories. */ + int pd; + for(pd = 0; pd < MAX_PAGEDIR_PDES; pd++) { + struct pdm *pdm = &pagedir_mappings[pd]; + if(!pdm->pdeno) { + pdm->pdeno = freepde(); + assert(pdm->pdeno); + } + phys_bytes ph; + + /* Allocate us a page table in which to + * remember page directory pointers. + */ + if(!(pdm->page_directories = + vm_allocpage(&ph, VMP_PAGETABLE))) { + panic("no virt addr for vm mappings"); + } + memset(pdm->page_directories, 0, VM_PAGE_SIZE); + pdm->phys = ph; + +#if defined(__i386__) + pdm->val = (ph & ARCH_VM_ADDR_MASK) | + ARCH_VM_PDE_PRESENT | ARCH_VM_PTE_RW; +#elif defined(__arm__) + pdm->val = (ph & ARCH_VM_PDE_MASK) + | ARCH_VM_PDE_PRESENT + | ARM_VM_PTE_CACHED + | ARM_VM_PDE_DOMAIN; //LSC FIXME +#endif + } +} + /*===========================================================================* * pt_init * *===========================================================================*/ @@ -1031,6 +1079,7 @@ void pt_init(void) { pt_t *newpt; int s, r, p; + phys_bytes phys; vir_bytes sparepages_mem; #if defined(__arm__) vir_bytes sparepagedirs_mem; @@ -1181,35 +1230,7 @@ void pt_init(void) } } - /* Reserve PDEs available for mapping in the page directories. */ - { - int pd; - for(pd = 0; pd < MAX_PAGEDIR_PDES; pd++) { - struct pdm *pdm = &pagedir_mappings[pd]; - pdm->pdeno = freepde(); - phys_bytes ph; - - /* Allocate us a page table in which to - * remember page directory pointers. - */ - if(!(pdm->page_directories = - vm_allocpage(&ph, VMP_PAGETABLE))) { - panic("no virt addr for vm mappings"); - } - memset(pdm->page_directories, 0, VM_PAGE_SIZE); - pdm->phys = ph; - -#if defined(__i386__) - pdm->val = (ph & ARCH_VM_ADDR_MASK) | - ARCH_VM_PDE_PRESENT | ARCH_VM_PTE_RW; -#elif defined(__arm__) - pdm->val = (ph & ARCH_VM_PDE_MASK) - | ARCH_VM_PDE_PRESENT - | ARM_VM_PTE_CACHED - | ARM_VM_PDE_DOMAIN; //LSC FIXME -#endif - } - } + pt_allocate_kernel_mapped_pagetables(); /* Allright. Now. We have to make our own page directory and page tables, * that the kernel has already set up, accessible to us. It's easier to @@ -1279,6 +1300,27 @@ void pt_init(void) pt_init_done = 1; + /* VM is now fully functional in that it can dynamically allocate memory + * for itself. + * + * We don't want to keep using the bootstrap statically allocated spare + * pages though, as the physical addresses will change on liveupdate. So we + * re-do part of the initialization now with purely dynamically allocated + * memory. First throw out the static pool. + */ + + alloc_cycle(); /* Make sure allocating works */ + while(vm_getsparepage(&phys)) ; /* Use up all static pages */ + alloc_cycle(); /* Refill spares with dynamic */ + pt_allocate_kernel_mapped_pagetables(); /* Reallocate in-kernel pages */ + pt_bind(newpt, &vmproc[VM_PROC_NR]); /* Recalculate */ + pt_mapkernel(newpt); /* Rewrite pagetable info */ + + /* Flush TLB just in case any of those mappings have been touched */ + if((sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) { + panic("VMCTL_FLUSHTLB failed"); + } + /* All OK. */ return; } diff --git a/minix/servers/vm/proto.h b/minix/servers/vm/proto.h index 79d3ac4c6..546fe1734 100644 --- a/minix/servers/vm/proto.h +++ b/minix/servers/vm/proto.h @@ -118,6 +118,7 @@ void vm_pagelock(void *vir, int lockflag); int vm_addrok(void *vir, int write); int get_vm_self_pages(void); int pt_writable(struct vmproc *vmp, vir_bytes v); +void pt_assert(pt_t *pt); #if SANITYCHECKS void pt_sanitycheck(pt_t *pt, const char *file, int line); diff --git a/minix/servers/vm/region.c b/minix/servers/vm/region.c index 5816b747c..2afc4080a 100644 --- a/minix/servers/vm/region.c +++ b/minix/servers/vm/region.c @@ -783,6 +783,7 @@ int map_pin_memory(struct vmproc *vmp) region_iter iter; region_start_iter_least(&vmp->vm_regions_avl, &iter); /* Scan all memory regions. */ + pt_assert(&vmp->vm_pt); while((vr = region_get_iter(&iter))) { /* Make sure region is mapped to physical memory and writable.*/ r = map_handle_memory(vmp, vr, 0, vr->length, 1, NULL, 0, 0); @@ -791,6 +792,7 @@ int map_pin_memory(struct vmproc *vmp) } region_incr_iter(&iter); } + pt_assert(&vmp->vm_pt); return OK; } diff --git a/minix/servers/vm/rs.c b/minix/servers/vm/rs.c index 38d56bd25..d6c2ac8be 100644 --- a/minix/servers/vm/rs.c +++ b/minix/servers/vm/rs.c @@ -146,6 +146,8 @@ static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp) this_vm_vmp = &vmproc[VM_PROC_NR]; + pt_assert(&this_vm_vmp->vm_pt); + /* Check if the operation is allowed. */ assert(num_vm_instances == 1 || num_vm_instances == 2); if(num_vm_instances == 2) { @@ -169,12 +171,12 @@ static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp) flags = 0; verify = FALSE; r = pt_ptalloc_in_range(&this_vm_vmp->vm_pt, - kernel_boot_info.freepde_start, ARCH_VM_DIR_ENTRIES, flags, verify); + VM_OWN_HEAPBASE, VM_DATATOP, flags, verify); if(r != OK) { return r; } r = pt_ptalloc_in_range(&new_vm_vmp->vm_pt, - kernel_boot_info.freepde_start, ARCH_VM_DIR_ENTRIES, flags, verify); + VM_OWN_HEAPBASE, VM_DATATOP, flags, verify); if(r != OK) { return r; } @@ -189,6 +191,9 @@ static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp) return r; } + pt_assert(&this_vm_vmp->vm_pt); + pt_assert(&new_vm_vmp->vm_pt); + return OK; }