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