Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / nds32 / mm / mm-nds32.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2005-2017 Andes Technology Corporation
3
4 #include <linux/init_task.h>
5 #include <asm/pgalloc.h>
6
7 #define FIRST_KERNEL_PGD_NR     (USER_PTRS_PER_PGD)
8
9 /*
10  * need to get a page for level 1
11  */
12
13 pgd_t *pgd_alloc(struct mm_struct *mm)
14 {
15         pgd_t *new_pgd, *init_pgd;
16         int i;
17
18         new_pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, 0);
19         if (!new_pgd)
20                 return NULL;
21         for (i = 0; i < PTRS_PER_PGD; i++) {
22                 (*new_pgd) = 1;
23                 new_pgd++;
24         }
25         new_pgd -= PTRS_PER_PGD;
26
27         init_pgd = pgd_offset_k(0);
28
29         memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
30                (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
31
32         cpu_dcache_wb_range((unsigned long)new_pgd,
33                             (unsigned long)new_pgd +
34                             PTRS_PER_PGD * sizeof(pgd_t));
35         inc_zone_page_state(virt_to_page((unsigned long *)new_pgd),
36                             NR_PAGETABLE);
37
38         return new_pgd;
39 }
40
41 void pgd_free(struct mm_struct *mm, pgd_t * pgd)
42 {
43         pmd_t *pmd;
44         struct page *pte;
45
46         if (!pgd)
47                 return;
48
49         pmd = (pmd_t *) pgd;
50         if (pmd_none(*pmd))
51                 goto free;
52         if (pmd_bad(*pmd)) {
53                 pmd_ERROR(*pmd);
54                 pmd_clear(pmd);
55                 goto free;
56         }
57
58         pte = pmd_page(*pmd);
59         pmd_clear(pmd);
60         dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
61         pte_free(mm, pte);
62         mm_dec_nr_ptes(mm);
63         pmd_free(mm, pmd);
64 free:
65         free_pages((unsigned long)pgd, 0);
66 }
67
68 /*
69  * In order to soft-boot, we need to insert a 1:1 mapping in place of
70  * the user-mode pages.  This will then ensure that we have predictable
71  * results when turning the mmu off
72  */
73 void setup_mm_for_reboot(char mode)
74 {
75         unsigned long pmdval;
76         pgd_t *pgd;
77         pmd_t *pmd;
78         int i;
79
80         if (current->mm && current->mm->pgd)
81                 pgd = current->mm->pgd;
82         else
83                 pgd = init_mm.pgd;
84
85         for (i = 0; i < USER_PTRS_PER_PGD; i++) {
86                 pmdval = (i << PGDIR_SHIFT);
87                 pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
88                 set_pmd(pmd, __pmd(pmdval));
89         }
90 }