From 0d984b36efb2b9dcfa16e114ec43e8338267ca44 Mon Sep 17 00:00:00 2001 From: Cristiano Giuffrida Date: Tue, 20 Jul 2010 21:59:27 +0000 Subject: [PATCH] Get rid of static spare pages after VM startup. --- kernel/arch/i386/arch_do_vmctl.c | 3 ++ servers/vm/arch/i386/pagetable.c | 91 ++++++++++++++++++++++++++++++-- servers/vm/main.c | 3 ++ servers/vm/proto.h | 1 + 4 files changed, 95 insertions(+), 3 deletions(-) diff --git a/kernel/arch/i386/arch_do_vmctl.c b/kernel/arch/i386/arch_do_vmctl.c index a1be5e39d..8a573e3a5 100644 --- a/kernel/arch/i386/arch_do_vmctl.c +++ b/kernel/arch/i386/arch_do_vmctl.c @@ -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; diff --git a/servers/vm/arch/i386/pagetable.c b/servers/vm/arch/i386/pagetable.c index 9c836e279..1fb5c9477 100644 --- a/servers/vm/arch/i386/pagetable.c +++ b/servers/vm/arch/i386/pagetable.c @@ -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 * diff --git a/servers/vm/main.c b/servers/vm/main.c index 03540a62a..0ee74440a 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -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; diff --git a/servers/vm/proto.h b/servers/vm/proto.h index e19b202ce..05ef411e6 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -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) );