]> Zhao Yanbai Git Server - minix.git/commitdiff
Get rid of static spare pages after VM startup.
authorCristiano Giuffrida <cristiano@minix3.org>
Tue, 20 Jul 2010 21:59:27 +0000 (21:59 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Tue, 20 Jul 2010 21:59:27 +0000 (21:59 +0000)
kernel/arch/i386/arch_do_vmctl.c
servers/vm/arch/i386/pagetable.c
servers/vm/main.c
servers/vm/proto.h

index a1be5e39d85732b43296824b1d831d2931bd932a..8a573e3a5f1523b2318467d7982c09d6eecaae08 100644 (file)
@@ -30,6 +30,9 @@ struct proc *p;
                        p->p_seg.p_cr3 = m_ptr->SVMCTL_PTROOT;
                        p->p_seg.p_cr3_v = (u32_t *) m_ptr->SVMCTL_PTROOT_V;
                        p->p_misc_flags |= MF_FULLVM;
+                       if(p == ptproc) {
+                               write_cr3(p->p_seg.p_cr3);
+                       }
                } else {
                        p->p_seg.p_cr3 = 0;
                        p->p_seg.p_cr3_v = NULL;
index 9c836e279fcc478f1fc0ae7e543df3e2a0ab3c5f..1fb5c9477844bbe08a78880ec57a06219447660e 100644 (file)
@@ -88,7 +88,9 @@ int kernmappings = 0;
 /* Page table that contains pointers to all page directories. */
 u32_t page_directories_phys, *page_directories = NULL;
 
-PRIVATE char static_sparepages[I386_PAGE_SIZE*SPAREPAGES + I386_PAGE_SIZE];
+#define STATIC_SPAREPAGES 10
+
+PRIVATE char static_sparepages[I386_PAGE_SIZE*STATIC_SPAREPAGES + I386_PAGE_SIZE];
 
 #if SANITYCHECKS
 /*===========================================================================*
@@ -750,13 +752,18 @@ PUBLIC void pt_init(phys_bytes usedlimit)
                 I386_PAGE_SIZE*SPAREPAGES, &sparepages_ph)) != OK)
                 panic("pt_init: sys_umap failed: %d", r);
 
+        missing_spares = 0;
+        assert(STATIC_SPAREPAGES < SPAREPAGES);
         for(s = 0; s < SPAREPAGES; s++) {
+               if(s >= STATIC_SPAREPAGES) {
+                       sparepages[s].page = NULL;
+                       missing_spares++;
+                       continue;
+               }
                sparepages[s].page = (void *) (sparepages_mem + s*I386_PAGE_SIZE);
                sparepages[s].phys = sparepages_ph + s*I386_PAGE_SIZE;
         }
 
-       missing_spares = 0;
-
        /* global bit and 4MB pages available? */
        global_bit_ok = _cpufeature(_CPUF_I386_PGE);
        bigpage_ok = _cpufeature(_CPUF_I386_PSE);
@@ -918,6 +925,84 @@ PUBLIC void pt_init(phys_bytes usedlimit)
         return;
 }
 
+/*===========================================================================*
+ *                             pt_init_mem                                   *
+ *===========================================================================*/
+PUBLIC void pt_init_mem()
+{
+/* Architecture-specific memory initialization. Make sure all the pages
+ * shared with the kernel and VM's page tables are mapped above the stack,
+ * so that we can easily transfer existing mappings for new VM instances.
+ */
+        u32_t new_page_directories_phys, *new_page_directories;
+        u32_t new_pt_dir_phys, *new_pt_dir;
+        u32_t new_pt_phys, *new_pt; 
+        pt_t *vmpt;
+        int i;
+
+        vmpt = &vmprocess->vm_pt;
+
+        /* We should be running this when VM has been assigned a page
+         * table and memory initialization has already been performed.
+         */
+        assert(vmprocess->vm_flags & VMF_HASPT);
+        assert(meminit_done);
+
+        /* Throw away static spare pages. */
+       vm_checkspares();
+       for(i = 0; i < SPAREPAGES; i++) {
+               if(sparepages[i].page && (vir_bytes) sparepages[i].page
+                       < vmprocess->vm_stacktop) {
+                       sparepages[i].page = NULL;
+                       missing_spares++;
+               }
+       }
+       vm_checkspares();
+
+        /* Rellocate page for page directories pointers. */
+       if(!(new_page_directories = vm_allocpage(&new_page_directories_phys,
+               VMP_PAGETABLE)))
+                panic("unable to reallocated page for page dir ptrs");
+       assert((vir_bytes) new_page_directories >= vmprocess->vm_stacktop);
+       memcpy(new_page_directories, page_directories, I386_PAGE_SIZE);
+       page_directories = new_page_directories;
+       pagedir_pde_val = (new_page_directories_phys & I386_VM_ADDR_MASK) |
+                       (pagedir_pde_val & ~I386_VM_ADDR_MASK);
+
+       /* Remap in kernel. */
+       pt_mapkernel(vmpt);
+
+       /* Reallocate VM's page directory. */
+       if((vir_bytes) vmpt->pt_dir < vmprocess->vm_stacktop) {
+               if(!(new_pt_dir= vm_allocpage(&new_pt_dir_phys, VMP_PAGEDIR))) {
+                       panic("unable to reallocate VM's page directory");
+               }
+               assert((vir_bytes) new_pt_dir >= vmprocess->vm_stacktop);
+               memcpy(new_pt_dir, vmpt->pt_dir, I386_PAGE_SIZE);
+               vmpt->pt_dir = new_pt_dir;
+               vmpt->pt_dir_phys = new_pt_dir_phys;
+               pt_bind(vmpt, vmprocess);
+       }
+
+       /* Reallocate VM's page tables. */
+       for(i = proc_pde; i < I386_VM_DIR_ENTRIES; i++) {
+               if(!(vmpt->pt_dir[i] & I386_VM_PRESENT)) {
+                       continue;
+               }
+               assert(vmpt->pt_pt[i]);
+               if((vir_bytes) vmpt->pt_pt[i] >= vmprocess->vm_stacktop) {
+                       continue;
+               }
+               vm_checkspares();
+               if(!(new_pt = vm_allocpage(&new_pt_phys, VMP_PAGETABLE)))
+                       panic("unable to reallocate VM's page table");
+               assert((vir_bytes) new_pt >= vmprocess->vm_stacktop);
+               memcpy(new_pt, vmpt->pt_pt[i], I386_PAGE_SIZE);
+               vmpt->pt_pt[i] = new_pt;
+               vmpt->pt_dir[i] = (new_pt_phys & I386_VM_ADDR_MASK) |
+                       (vmpt->pt_dir[i] & ~I386_VM_ADDR_MASK);
+       }
+}
 
 /*===========================================================================*
  *                             pt_bind                                      *
index 03540a62a5b530bcbc8be77361dd9de1474116f9..0ee74440a91d2261050e2ce81ca2f976142e87c7 100644 (file)
@@ -262,6 +262,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        mem_init(mem_chunks);
        meminit_done = 1;
 
+       /* Architecture-dependent memory initialization. */
+       pt_init_mem();
+
        /* Give these processes their own page table. */
        for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
                int s;
index e19b202ced1ae96712cfe508f94485132dfed076..05ef411e6e10c53c552e5aabc055f7e52c1b28ea 100644 (file)
@@ -97,6 +97,7 @@ _PROTOTYPE( int handle_memory, (struct vmproc *vmp, vir_bytes mem,
 
 /* $(ARCH)/pagetable.c */
 _PROTOTYPE( void pt_init, (phys_bytes limit)                           );
+_PROTOTYPE( void pt_init_mem, (void)                                   );
 _PROTOTYPE( void pt_check, (struct vmproc *vmp)                                );
 _PROTOTYPE( int pt_new, (pt_t *pt)                                     );
 _PROTOTYPE( void pt_free, (pt_t *pt)                                   );