pgd_t *get_pgd_slow(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; new_pgd = alloc_pgd_table(GFP_KERNEL); if (!new_pgd) goto no_pgd; /* * This lock is here just to satisfy pmd_alloc and pte_lock */ spin_lock(&mm->page_table_lock); /* * On ARM, first page must always be allocated since it contains * the machine vectors. */ new_pmd = pmd_alloc(mm, new_pgd, 0); if (!new_pmd) goto no_pmd; new_pte = pte_alloc(mm, new_pmd, 0); if (!new_pte) goto no_pte; init_pgd = pgd_offset_k(0); init_pmd = pmd_offset(init_pgd, 0); init_pte = pte_offset(init_pmd, 0); set_pte(new_pte, *init_pte); /* * most of the page table entries are zeroed * wne the table is created. */ memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); spin_unlock(&mm->page_table_lock); /* update MEMC tables */ cpu_memc_update_all(new_pgd); return new_pgd; no_pte: spin_unlock(&mm->page_table_lock); pmd_free(new_pmd); free_pgd_slow(new_pgd); return NULL; no_pmd: spin_unlock(&mm->page_table_lock); free_pgd_slow(new_pgd); return NULL; no_pgd: return NULL; }
pgd_t *get_pgd_slow(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; new_pgd = alloc_pgd_table(); if (!new_pgd) goto no_pgd; /* * On ARM, first page must always be allocated since it contains * the machine vectors. */ new_pmd = pmd_alloc(mm, new_pgd, 0); if (!new_pmd) goto no_pmd; new_pte = pte_alloc_map(mm, new_pmd, 0); if (!new_pte) goto no_pte; init_pgd = pgd_offset(&init_mm, 0); init_pmd = pmd_offset(init_pgd, 0); init_pte = pte_offset(init_pmd, 0); set_pte(new_pte, *init_pte); pte_unmap(new_pte); /* * the page table entries are zeroed * when the table is created. (see the cache_ctor functions below) * Now we need to plonk the kernel (vmalloc) area at the end of * the address space. We copy this from the init thread, just like * the init_pte we copied above... */ memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); /* update MEMC tables */ cpu_memc_update_all(new_pgd); return new_pgd; no_pte: pmd_free(new_pmd); no_pmd: free_pgd_slow(new_pgd); no_pgd: return NULL; }
pgd_t *get_pgd_slow(void) { pgd_t *pgd = (pgd_t *)alloc_pgd_table(GFP_KERNEL); pmd_t *new_pmd; if (pgd) { pgd_t *init = pgd_offset(&init_mm, 0); memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t)); memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); /* * On ARM, first page must always be allocated */ if (!pmd_alloc(pgd, 0)) goto nomem; else { pmd_t *old_pmd = pmd_offset(init, 0); new_pmd = pmd_offset(pgd, 0); if (!pte_alloc(new_pmd, 0)) goto nomem_pmd; else { pte_t *new_pte = pte_offset(new_pmd, 0); pte_t *old_pte = pte_offset(old_pmd, 0); set_pte (new_pte, *old_pte); } } /* update MEMC tables */ cpu_memc_update_all(pgd); } return pgd; nomem_pmd: pmd_free(new_pmd); nomem: free_pgd_slow(pgd); return NULL; }