1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2020 Loongson Technology Corporation Limited
4 */
5#include <linux/export.h>
6#include <linux/init.h>
7#include <linux/mm.h>
8#include <asm/fixmap.h>
9#include <asm/pgtable.h>
10#include <asm/pgalloc.h>
11#include <asm/tlbflush.h>
12
13void pgd_init(unsigned long page)
14{
15	unsigned long *p, *end;
16	unsigned long entry;
17
18#if !defined(__PAGETABLE_PUD_FOLDED)
19	entry = (unsigned long)invalid_pud_table;
20#elif !defined(__PAGETABLE_PMD_FOLDED)
21	entry = (unsigned long)invalid_pmd_table;
22#else
23	entry = (unsigned long)invalid_pte_table;
24#endif
25
26	p = (unsigned long *) page;
27	end = p + PTRS_PER_PGD;
28
29	do {
30		p[0] = entry;
31		p[1] = entry;
32		p[2] = entry;
33		p[3] = entry;
34		p[4] = entry;
35		p += 8;
36		p[-3] = entry;
37		p[-2] = entry;
38		p[-1] = entry;
39	} while (p != end);
40}
41EXPORT_SYMBOL_GPL(pgd_init);
42
43#ifndef __PAGETABLE_PMD_FOLDED
44void pmd_init(unsigned long addr, unsigned long pagetable)
45{
46	unsigned long *p, *end;
47
48	p = (unsigned long *) addr;
49	end = p + PTRS_PER_PMD;
50
51	do {
52		p[0] = pagetable;
53		p[1] = pagetable;
54		p[2] = pagetable;
55		p[3] = pagetable;
56		p[4] = pagetable;
57		p += 8;
58		p[-3] = pagetable;
59		p[-2] = pagetable;
60		p[-1] = pagetable;
61	} while (p != end);
62}
63EXPORT_SYMBOL_GPL(pmd_init);
64#endif
65
66#ifndef __PAGETABLE_PUD_FOLDED
67void pud_init(unsigned long addr, unsigned long pagetable)
68{
69	unsigned long *p, *end;
70
71	p = (unsigned long *)addr;
72	end = p + PTRS_PER_PUD;
73
74	do {
75		p[0] = pagetable;
76		p[1] = pagetable;
77		p[2] = pagetable;
78		p[3] = pagetable;
79		p[4] = pagetable;
80		p += 8;
81		p[-3] = pagetable;
82		p[-2] = pagetable;
83		p[-1] = pagetable;
84	} while (p != end);
85}
86#endif
87
88pmd_t mk_pmd(struct page *page, pgprot_t prot)
89{
90	pmd_t pmd;
91
92	pmd_val(pmd) = (page_to_pfn(page) << _PFN_SHIFT) | pgprot_val(prot);
93
94	return pmd;
95}
96
97void set_pmd_at(struct mm_struct *mm, unsigned long addr,
98		pmd_t *pmdp, pmd_t pmd)
99{
100	*pmdp = pmd;
101	flush_tlb_all();
102}
103
104void __init pagetable_init(void)
105{
106	unsigned long vaddr;
107
108	/* Initialize the entire pgd.  */
109	pgd_init((unsigned long)swapper_pg_dir);
110	pgd_init((unsigned long)invalid_pg_dir);
111#ifndef __PAGETABLE_PUD_FOLDED
112	pud_init((unsigned long)invalid_pud_table, (unsigned long)invalid_pmd_table);
113#endif
114#ifndef __PAGETABLE_PMD_FOLDED
115	pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
116#endif
117	/*
118	 * Fixed mappings:
119	 */
120	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
121}
122