// // Frees env e and all memory it uses. // void env_free(struct Env *e) { pte_t *pt; uint32_t pdeno, pteno; physaddr_t pa; // If freeing the current environment, switch to boot_pgdir // before freeing the page directory, just in case the page // gets reused. if (e == curenv) lcr3(boot_cr3); // Note the environment's demise. // cprintf("[%08x] free env %08x\n", curenv ? curenv->env_id : 0, e->env_id); // Flush all mapped pages in the user portion of the address space static_assert(UTOP % PTSIZE == 0); for (pdeno = 0; pdeno < PDX(UTOP); pdeno++) { // only look at mapped page tables if (!(e->env_pgdir[pdeno] & PTE_P)) continue; // find the pa and va of the page table pa = PTE_ADDR(e->env_pgdir[pdeno]); pt = (pte_t*) KADDR(pa); // unmap all PTEs in this page table for (pteno = 0; pteno <= PTX(~0); pteno++) { if (pt[pteno] & PTE_P) page_remove(e->env_pgdir, PGADDR(pdeno, pteno, 0)); } // free the page table itself e->env_pgdir[pdeno] = 0; page_decref(pa2page(pa)); } // free the page directory pa = e->env_cr3; e->env_pgdir = 0; e->env_cr3 = 0; page_decref(pa2page(pa)); // return the environment to the free list e->env_status = ENV_FREE; LIST_INSERT_HEAD(&env_free_list, e, env_link); }
static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring) { panic("Disabled"); #if 0 // AKAROS_PORT struct mlx4_en_rx_alloc *page_alloc; int i; for (i = 0; i < priv->num_frags; i++) { const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; page_alloc = &ring->page_alloc[i]; en_dbg(DRV, priv, "Freeing allocator:%d count:%d\n", i, page_count(page_alloc->page)); dma_unmap_page(priv->ddev, page_alloc->dma, page_alloc->page_size, PCI_DMA_FROMDEVICE); while (page_alloc->page_offset + frag_info->frag_stride < page_alloc->page_size) { page_decref(page_alloc->page); page_alloc->page_offset += frag_info->frag_stride; } page_alloc->page = NULL; } #endif }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in struct PageInfo *pg; pte_t *pte; pte_t **pte_store=&pte; pg=page_lookup(pgdir,va,pte_store); // If there is no physical page at that address, silently does nothing. if (!pg) {cprintf("page not found \n"); return;} // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. page_decref(pg); //cprintf("page ref after decrement : %d \n",pg->pp_ref); //- The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) if(pte_store){ **pte_store=0; // - The TLB must be invalidated if you remove an entry from // the page table. tlb_invalidate(pgdir,va); } }
// Initialize the kernel virtual memory layout for environment e. // Allocate a page directory, set e->env_pgdir and e->env_cr3 accordingly, // and initialize the kernel portion of the new environment's address space. // Do NOT (yet) map anything into the user portion // of the environment's virtual address space. // // Returns 0 on success, < 0 on error. Errors include: // -ENOMEM if page directory or table could not be allocated. // int env_setup_vm(env_t *e) { int i, ret; static page_t *shared_page = 0; if ((ret = arch_pgdir_setup(boot_pgdir, &e->env_pgdir))) return ret; /* TODO: verify there is nothing below ULIM */ e->env_cr3 = arch_pgdir_get_cr3(e->env_pgdir); /* These need to be contiguous, so the kernel can alias them. Note the * pages return with a refcnt, but it's okay to insert them since we free * them manually when the process is cleaned up. */ if (!(e->procinfo = get_cont_pages(LOG2_UP(PROCINFO_NUM_PAGES), 0))) goto env_setup_vm_error_i; if (!(e->procdata = get_cont_pages(LOG2_UP(PROCDATA_NUM_PAGES), 0))) goto env_setup_vm_error_d; /* Normally we'd 0 the pages here. We handle it in proc_init_proc*. Don't * start the process without calling those. */ for (int i = 0; i < PROCINFO_NUM_PAGES; i++) { if (page_insert(e->env_pgdir, kva2page((void*)e->procinfo + i * PGSIZE), (void*)(UINFO + i*PGSIZE), PTE_USER_RO) < 0) goto env_setup_vm_error; } for (int i = 0; i < PROCDATA_NUM_PAGES; i++) { if (page_insert(e->env_pgdir, kva2page((void*)e->procdata + i * PGSIZE), (void*)(UDATA + i*PGSIZE), PTE_USER_RW) < 0) goto env_setup_vm_error; } for (int i = 0; i < PROCGINFO_NUM_PAGES; i++) { if (page_insert(e->env_pgdir, kva2page((void*)&__proc_global_info + i * PGSIZE), (void*)(UGINFO + i * PGSIZE), PTE_USER_RO) < 0) goto env_setup_vm_error; } /* Finally, set up the Global Shared Data page for all processes. Can't be * trusted, but still very useful at this stage for us. Consider removing * when we have real processes (TODO). * * Note the page is alloced only the first time through, and its ref is * stored in shared_page. */ if (!shared_page) { if (upage_alloc(e, &shared_page, 1) < 0) goto env_setup_vm_error; } if (page_insert(e->env_pgdir, shared_page, (void*)UGDATA, PTE_USER_RW) < 0) goto env_setup_vm_error; return 0; env_setup_vm_error: free_cont_pages(e->procdata, LOG2_UP(PROCDATA_NUM_PAGES)); env_setup_vm_error_d: free_cont_pages(e->procinfo, LOG2_UP(PROCINFO_NUM_PAGES)); env_setup_vm_error_i: page_decref(shared_page); env_user_mem_free(e, 0, UVPT); env_pagetable_free(e); return -ENOMEM; }
void vector_clear(Vector *v) { assert(v->elem != NULL); page_decref(kva2page(v->elem)); v->elem = NULL; v->size = v->capacity = 0; }
int exit_mm(struct mm_struct *mm) { pmd_t *pmd; pgd_t *pgd; uint32_t pgdno, pmdno; physaddr_t pa; struct vm_area_struct* vma = mm->mmap; struct page *page; if(!mm || !mm->mm_pgd) return 0; if(!atomic_dec_and_test(&mm->mm_count)) return 0; delete_all_vma(mm); for (pgdno = 0; pgdno < pgd_index(KERNEL_BASE_ADDR); pgdno++) { pgd = mm->mm_pgd + pgdno; if(!pgd_present(*pgd) || pgd_none(*pgd)) continue; pmd_t* tmp = (pmd_t *)pgd_page_vaddr(*pgd); for (pmdno = 0; pmdno < PTRS_PER_PMD; pmdno++) { pmd = tmp + pmdno; if(!pmd_present(*pmd) || pmd_none(*pmd)) continue; struct page* p = virt2page(pmd_page_vaddr(*pmd)); page_decref(p); pmd_set(pmd,0,0); } struct page* p = virt2page(pgd_page_vaddr(*pgd)); page_decref(p); pgd_set(pgd,0,0); } page = virt2page((viraddr_t)mm->mm_pgd); page_free(page); kfree(mm); return 0; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, uintptr_t va) { pte_t *pte; Page *pp = page_lookup(pgdir, va, &pte); if (pp != NULL) { page_decref(pp); *pte = *pte & ~0x1; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *pte; struct PageInfo *pp = page_lookup(pgdir, va, &pte); if (!pp || !(*pte & PTE_P)) return; page_decref(pp); *pte = 0; tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *tmppte; struct PageInfo *tmp = page_lookup(pgdir, va, &tmppte); if( tmp != NULL && (*tmppte & PTE_P)) { page_decref(tmp); *tmppte = 0; } tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t* pte_store = NULL; struct PageInfo* pg = page_lookup(pgdir, va, &pte_store); if (!pg) return; page_decref(pg); tlb_invalidate(pgdir, va); *pte_store = 0; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t * pte_page; struct Page * page = page_lookup(pgdir, va, &pte_page); if(page) { page_decref(page); (* pte_page) = 0; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t *pte; struct Page* pp = page_lookup(pgdir, va, &pte); if (pp) { page_decref(pp); *pte = 0; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t *table_entry; struct PageInfo *page = page_lookup(pgdir, va, &table_entry); if (page) { // Decrement/free page, reset table entry, and invalidate TLB entry. page_decref(page); *table_entry = 0x0; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pml4e_t *pml4e, void *va) { // Fill this function in pte_t* pte = NULL; struct Page *page = page_lookup(pml4e, va, &pte); if(page != 0){ page_decref(page); *pte = 0; tlb_invalidate(pml4e, va); } }
// // Invalidate a TLB entry, but only if the page tables being // edited are the ones currently in use by the processor. // void tlb_invalidate(pde_t *pgdir, void *va) { // Flush the entry only if we're modifying the current address space. // For now, there is only one address space, so always invalidate. pte_t *tmppte; struct PageInfo *tmp = page_lookup(pgdir, va, &tmppte); if( tmp != NULL) { page_decref(tmp); *tmppte = 0; } invlpg(va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t* pte; struct Page* pp = page_lookup(pgdir, va, &pte); if (pp != NULL) { *pte = 0; page_decref(pp); tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t* pte; struct Page* res; res=page_lookup(pgdir,va,&pte); if(res!=NULL) { page_decref(res); *pte=0; tlb_invalidate(pgdir,va); } }
static void free_ept_level(epte_t* eptrt, int level) { epte_t* dir = eptrt; int i; for(i=0; i<NPTENTRIES; ++i) { if(level != 0) { if(epte_present(dir[i])) { physaddr_t pa = epte_addr(dir[i]); free_ept_level((epte_t*) KADDR(pa), level-1); // free the table. page_decref(pa2page(pa)); } } else { // Last level, free the guest physical page. if(epte_present(dir[i])) { physaddr_t pa = epte_addr(dir[i]); page_decref(pa2page(pa)); } } } return; }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in //bluesea struct PageInfo *page = NULL; pte_t *ptep = NULL; if ((page = page_lookup(pgdir, va, &ptep)) != NULL){ page_decref(page); *ptep = *ptep & (0xfff & ~PTE_P); tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Lookup the page and store into page_table_entry pte_t * page_table_entry = NULL; struct PageInfo * page_info = page_lookup(pgdir, va, &page_table_entry); if (page_info != NULL) { // Decrement the counter and free if the refcount reaches zero page_decref(page_info); *page_table_entry = 0; tlb_invalidate(pgdir, va); } }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *pte_store; struct PageInfo *pp = page_lookup(pgdir, va, &pte_store); if(!pte_store || !(pte_store[0] & PTE_P)){ return ; } page_decref(pp); *pte_store = 0; tlb_invalidate(pgdir, va); }
void page_remove(pgd_t* pgdir, viraddr_t va) { assert(pgdir); page_t *pf; pte_t *pte_store; pf = page_lookup(pgdir, va, &pte_store); if( pf == NULL ) return; //printk("free:%x\n",va); page_decref(pf); pte_set(*pte_store,0); refresh_tlb(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in /*stone's solution for lab2*/ pte_t* pte; struct Page* pp = page_lookup(pgdir, va, &pte); if (pp != NULL){ *pte = 0; page_decref(pp); tlb_invalidate(pgdir, va); } return; }
void page_remove(pml4e_t *pml4, uintptr_t va) { struct page *p; pte_t *pte; p = page_lookup(pml4, va, &pte); if (p == NULL) // nothing to do return; page_decref(p); *pte = 0; invlpg((void *)va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *pte; struct Page *pp; if (!(pp = page_lookup(pgdir, va, &pte))) return; page_decref(pp); assert(pte); *pte = 0; tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t *pte; struct PageInfo *pg = page_lookup(pgdir, va, &pte); if (!pg || !(*pte & PTE_P)) return; //page not exist // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. page_decref(pg); // - The pg table entry corresponding to 'va' should be set to 0. *pte = 0; // - The TLB must be invalidated if you remove an entry from // the page table. tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { pte_t *pte = pgdir_walk(pgdir,va,0); if (pte == NULL || !(*pte & PTE_P)) { cprintf("remove an empty pte!\n"); return ; } struct Page *pp = page_lookup(pgdir,va,0); *pte = 0; page_decref(pp); tlb_invalidate(pgdir,va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t *ptep; struct PageInfo *pp = page_lookup(pgdir, va, &ptep); if(!pp) { return; } page_decref(pp); assert(ptep != NULL); *ptep = 0; tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in // SUNUS, 28, October, 2013 struct PageInfo *page; pte_t *pte = NULL; page = page_lookup(pgdir, va, &pte); if (!page) return ; page_decref(page); if (pte) { *pte = 0; } tlb_invalidate(pgdir, va); }
// // Unmaps the physical page at virtual address 'va'. // If there is no physical page at that address, silently does nothing. // // Details: // - The ref count on the physical page should decrement. // - The physical page should be freed if the refcount reaches 0. // - The pg table entry corresponding to 'va' should be set to 0. // (if such a PTE exists) // - The TLB must be invalidated if you remove an entry from // the page table. // // Hint: The TA solution is implemented using page_lookup, // tlb_invalidate, and page_decref. // void page_remove(pde_t *pgdir, void *va) { // Fill this function in pte_t* pte=pgdir_walk(pgdir,va,0); struct Page* pg; if(!pte && !(*pte) ) return ; pg=pa2page(PTE_ADDR(*pte)); *pte=0; tlb_invalidate(pgdir, va); page_decref(pg); }