12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- // SPDX-License-Identifier: GPL-2.0
- // Copyright (C) 2005-2017 Andes Technology Corporation
- #include <linux/init_task.h>
- #include <asm/pgalloc.h>
- #define FIRST_KERNEL_PGD_NR (USER_PTRS_PER_PGD)
- /*
- * need to get a page for level 1
- */
- pgd_t *pgd_alloc(struct mm_struct *mm)
- {
- pgd_t *new_pgd, *init_pgd;
- int i;
- new_pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, 0);
- if (!new_pgd)
- return NULL;
- for (i = 0; i < PTRS_PER_PGD; i++) {
- (*new_pgd) = 1;
- new_pgd++;
- }
- new_pgd -= PTRS_PER_PGD;
- init_pgd = pgd_offset_k(0);
- memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
- (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
- cpu_dcache_wb_range((unsigned long)new_pgd,
- (unsigned long)new_pgd +
- PTRS_PER_PGD * sizeof(pgd_t));
- inc_zone_page_state(virt_to_page((unsigned long *)new_pgd),
- NR_PAGETABLE);
- return new_pgd;
- }
- void pgd_free(struct mm_struct *mm, pgd_t * pgd)
- {
- pmd_t *pmd;
- struct page *pte;
- if (!pgd)
- return;
- pmd = (pmd_t *) pgd;
- if (pmd_none(*pmd))
- goto free;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- goto free;
- }
- pte = pmd_page(*pmd);
- pmd_clear(pmd);
- dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
- pte_free(mm, pte);
- mm_dec_nr_ptes(mm);
- pmd_free(mm, pmd);
- free:
- free_pages((unsigned long)pgd, 0);
- }
- /*
- * In order to soft-boot, we need to insert a 1:1 mapping in place of
- * the user-mode pages. This will then ensure that we have predictable
- * results when turning the mmu off
- */
- void setup_mm_for_reboot(char mode)
- {
- unsigned long pmdval;
- pgd_t *pgd;
- pmd_t *pmd;
- int i;
- if (current->mm && current->mm->pgd)
- pgd = current->mm->pgd;
- else
- pgd = init_mm.pgd;
- for (i = 0; i < USER_PTRS_PER_PGD; i++) {
- pmdval = (i << PGDIR_SHIFT);
- pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
- set_pmd(pmd, __pmd(pmdval));
- }
- }
|