xref: /linux/arch/xtensa/mm/mmu.c (revision 00a6d7b6762c27d441e9ac8faff36384bc0fc180)
1 /*
2  * xtensa mmu stuff
3  *
4  * Extracted from init.c
5  */
6 #include <linux/bootmem.h>
7 #include <linux/percpu.h>
8 #include <linux/init.h>
9 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/cache.h>
12 
13 #include <asm/tlb.h>
14 #include <asm/tlbflush.h>
15 #include <asm/mmu_context.h>
16 #include <asm/page.h>
17 #include <asm/initialize_mmu.h>
18 #include <asm/io.h>
19 
20 #if defined(CONFIG_HIGHMEM)
21 static void * __init init_pmd(unsigned long vaddr)
22 {
23 	pgd_t *pgd = pgd_offset_k(vaddr);
24 	pmd_t *pmd = pmd_offset(pgd, vaddr);
25 
26 	if (pmd_none(*pmd)) {
27 		unsigned i;
28 		pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);
29 
30 		for (i = 0; i < 1024; i++)
31 			pte_clear(NULL, 0, pte + i);
32 
33 		set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
34 		BUG_ON(pte != pte_offset_kernel(pmd, 0));
35 		pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",
36 			 __func__, vaddr, pmd, pte);
37 		return pte;
38 	} else {
39 		return pte_offset_kernel(pmd, 0);
40 	}
41 }
42 
43 static void __init fixedrange_init(void)
44 {
45 	BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
46 	init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
47 }
48 #endif
49 
50 void __init paging_init(void)
51 {
52 	memset(swapper_pg_dir, 0, PAGE_SIZE);
53 #ifdef CONFIG_HIGHMEM
54 	fixedrange_init();
55 	pkmap_page_table = init_pmd(PKMAP_BASE);
56 	kmap_init();
57 #endif
58 }
59 
60 /*
61  * Flush the mmu and reset associated register to default values.
62  */
63 void init_mmu(void)
64 {
65 #if !(XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)
66 	/*
67 	 * Writing zeros to the instruction and data TLBCFG special
68 	 * registers ensure that valid values exist in the register.
69 	 *
70 	 * For existing PGSZID<w> fields, zero selects the first element
71 	 * of the page-size array.  For nonexistent PGSZID<w> fields,
72 	 * zero is the best value to write.  Also, when changing PGSZID<w>
73 	 * fields, the corresponding TLB must be flushed.
74 	 */
75 	set_itlbcfg_register(0);
76 	set_dtlbcfg_register(0);
77 #endif
78 #if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
79 	/*
80 	 * Update the IO area mapping in case xtensa_kio_paddr has changed
81 	 */
82 	write_dtlb_entry(__pte(xtensa_kio_paddr + CA_WRITEBACK),
83 			XCHAL_KIO_CACHED_VADDR + 6);
84 	write_itlb_entry(__pte(xtensa_kio_paddr + CA_WRITEBACK),
85 			XCHAL_KIO_CACHED_VADDR + 6);
86 	write_dtlb_entry(__pte(xtensa_kio_paddr + CA_BYPASS),
87 			XCHAL_KIO_BYPASS_VADDR + 6);
88 	write_itlb_entry(__pte(xtensa_kio_paddr + CA_BYPASS),
89 			XCHAL_KIO_BYPASS_VADDR + 6);
90 #endif
91 
92 	local_flush_tlb_all();
93 
94 	/* Set rasid register to a known value. */
95 
96 	set_rasid_register(ASID_INSERT(ASID_USER_FIRST));
97 
98 	/* Set PTEVADDR special register to the start of the page
99 	 * table, which is in kernel mappable space (ie. not
100 	 * statically mapped).  This register's value is undefined on
101 	 * reset.
102 	 */
103 	set_ptevaddr_register(PGTABLE_START);
104 }
105