int vm_do_unmap(addr_t virt, unsigned locked) { /* This gives the virtual address of the table needed, and sets * the correct place as zero */ #if CONFIG_SWAP if(current_task && num_swapdev && current_task->num_swapped) swap_in_page((task_t *)current_task, virt & PAGE_MASK); #endif if(kernel_task && (virt&PAGE_MASK) != PDIR_DATA && !locked) mutex_acquire(&pd_cur_data->lock); addr_t p = page_tables[(virt&PAGE_MASK)/0x1000]; page_tables[(virt&PAGE_MASK)/0x1000] = 0; asm("invlpg (%0)"::"r" (virt)); #if CONFIG_SMP if(kernel_task && (virt&PAGE_MASK) != PDIR_DATA) { if(IS_KERN_MEM(virt)) send_ipi(LAPIC_ICR_SHORT_OTHERS, 0, LAPIC_ICR_LEVELASSERT | LAPIC_ICR_TM_LEVEL | IPI_TLB); else if((IS_THREAD_SHARED_MEM(virt) && pd_cur_data->count > 1)) send_ipi(LAPIC_ICR_SHORT_OTHERS, 0, LAPIC_ICR_LEVELASSERT | LAPIC_ICR_TM_LEVEL | IPI_TLB); } #endif if(kernel_task && (virt&PAGE_MASK) != PDIR_DATA && !locked) mutex_release(&pd_cur_data->lock); if(p && !(p & PAGE_COW)) pm_free_page(p & PAGE_MASK); return 0; }
int vm_do_unmap(addr_t virt, unsigned locked) { /* This gives the virtual address of the table needed, and sets * the correct place as zero */ #if CONFIG_SWAP if(current_task && num_swapdev && current_task->num_swapped) swap_in_page((task_t *)current_task, virt & PAGE_MASK); #endif addr_t vpage = (virt&PAGE_MASK)/0x1000; unsigned vp4 = PML4_IDX(vpage); unsigned vpdpt = PDPT_IDX(vpage); unsigned vdir = PAGE_DIR_IDX(vpage); unsigned vtbl = PAGE_TABLE_IDX(vpage); if(kernel_task && (virt&PAGE_MASK) != PDIR_DATA && !locked) mutex_acquire(&pd_cur_data->lock); page_dir_t *pd; page_table_t *pt; pdpt_t *pdpt; pml4_t *pml4; pml4 = (pml4_t *)((kernel_task && current_task) ? current_task->pd : kernel_dir); if(!pml4[vp4]) pml4[vp4] = pm_alloc_page() | PAGE_PRESENT | PAGE_WRITE; pdpt = (addr_t *)((pml4[vp4]&PAGE_MASK) + PHYS_PAGE_MAP); if(!pdpt[vpdpt]) pdpt[vpdpt] = pm_alloc_page() | PAGE_PRESENT | PAGE_WRITE; pd = (addr_t *)((pdpt[vpdpt]&PAGE_MASK) + PHYS_PAGE_MAP); if(!pd[vdir]) pd[vdir] = pm_alloc_page() | PAGE_PRESENT | PAGE_WRITE; pt = (addr_t *)((pd[vdir]&PAGE_MASK) + PHYS_PAGE_MAP); addr_t p = pt[vtbl]; pt[vtbl] = 0; asm("invlpg (%0)"::"r" (virt)); #if CONFIG_SMP if(kernel_task && (virt&PAGE_MASK) != PDIR_DATA) { if(IS_KERN_MEM(virt)) send_ipi(LAPIC_ICR_SHORT_OTHERS, 0, LAPIC_ICR_LEVELASSERT | LAPIC_ICR_TM_LEVEL | IPI_TLB); else if((IS_THREAD_SHARED_MEM(virt) && pd_cur_data->count > 1)) send_ipi(LAPIC_ICR_SHORT_OTHERS, 0, LAPIC_ICR_LEVELASSERT | LAPIC_ICR_TM_LEVEL | IPI_TLB); } #endif if(kernel_task && (virt&PAGE_MASK) != PDIR_DATA && !locked) mutex_release(&pd_cur_data->lock); if(p && !(p & PAGE_COW)) pm_free_page(p & PAGE_MASK); return 0; }
int free_stack() { unsigned int *pd = (unsigned *)current_task->pd; int T = PAGE_DIR_IDX(TOP_TASK_MEM/PAGE_SIZE); int S = PAGE_DIR_IDX(TOP_TASK_MEM_EXEC/PAGE_SIZE); int i=0; for(i=S;i<T;++i) { if(!pd[i]) continue; self_free_table(i); pm_free_page(pd[i]&PAGE_MASK); pd[i]=0; } return 0; }
int self_free(int all) { unsigned int *pd = (unsigned *)current_task->pd; int D = PAGE_DIR_IDX(TOP_TASK_MEM_EXEC/PAGE_SIZE); int A = PAGE_DIR_IDX(SOLIB_RELOC_START/PAGE_SIZE); int B = PAGE_DIR_IDX(SOLIB_RELOC_END/PAGE_SIZE); int i=0; for(i=id_tables;i<D;++i) { if(!pd[i]) continue; /* Only clear out shared libraries if we are exiting */ if(i >= A && i < B && !(current_task->flags & TF_EXITING)) continue; self_free_table(i); pm_free_page(pd[i]&PAGE_MASK); pd[i]=0; } return 0; }