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; }
static void __init map_node(int node) { #define PTRTREESIZE (256*1024) #define ROOTTREESIZE (32*1024*1024) unsigned long physaddr, virtaddr, size; pgd_t *pgd_dir; pmd_t *pmd_dir; pte_t *pte_dir; size = m68k_memory[node].size; physaddr = m68k_memory[node].addr; virtaddr = (unsigned long)phys_to_virt(physaddr); physaddr |= m68k_supervisor_cachemode | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY; if (CPU_IS_040_OR_060) physaddr |= _PAGE_GLOBAL040; while (size > 0) { #ifdef DEBUG if (!(virtaddr & (PTRTREESIZE-1))) printk ("\npa=%#lx va=%#lx ", physaddr & PAGE_MASK, virtaddr); #endif pgd_dir = pgd_offset_k(virtaddr); if (virtaddr && CPU_IS_020_OR_030) { if (!(virtaddr & (ROOTTREESIZE-1)) && size >= ROOTTREESIZE) { #ifdef DEBUG printk ("[very early term]"); #endif pgd_val(*pgd_dir) = physaddr; size -= ROOTTREESIZE; virtaddr += ROOTTREESIZE; physaddr += ROOTTREESIZE; continue; } } if (!pgd_present(*pgd_dir)) { pmd_dir = kernel_ptr_table(); #ifdef DEBUG printk ("[new pointer %p]", pmd_dir); #endif pgd_set(pgd_dir, pmd_dir); } else pmd_dir = pmd_offset(pgd_dir, virtaddr); if (CPU_IS_020_OR_030) { if (virtaddr) { #ifdef DEBUG printk ("[early term]"); #endif pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr; physaddr += PTRTREESIZE; } else { int i; #ifdef DEBUG printk ("[zero map]"); #endif zero_pgtable = kernel_ptr_table(); pte_dir = (pte_t *)zero_pgtable; pmd_dir->pmd[0] = virt_to_phys(pte_dir) | _PAGE_TABLE | _PAGE_ACCESSED; pte_val(*pte_dir++) = 0; physaddr += PAGE_SIZE; for (i = 1; i < 64; physaddr += PAGE_SIZE, i++) pte_val(*pte_dir++) = physaddr; } size -= PTRTREESIZE; virtaddr += PTRTREESIZE; } else { if (!pmd_present(*pmd_dir)) { #ifdef DEBUG printk ("[new table]"); #endif pte_dir = kernel_page_table(); pmd_set(pmd_dir, pte_dir); } pte_dir = pte_offset_kernel(pmd_dir, virtaddr); if (virtaddr) { if (!pte_present(*pte_dir)) pte_val(*pte_dir) = physaddr; } else pte_val(*pte_dir) = 0; size -= PAGE_SIZE; virtaddr += PAGE_SIZE; physaddr += PAGE_SIZE; } } #ifdef DEBUG printk("\n"); #endif }