1
2
3
4
5
6
7
8
9
10
11#include <linux/module.h>
12#include <linux/mm.h>
13#include <asm/cacheflush.h>
14#include <asm/smp.h>
15#include "cache-smp.h"
16
17
18
19
20
21
22
23
24
25void flush_icache_page(struct vm_area_struct *vma, struct page *page)
26{
27 unsigned long start = page_to_phys(page);
28 unsigned long flags;
29
30 flags = smp_lock_cache();
31
32 mn10300_local_dcache_flush_page(start);
33 mn10300_local_icache_inv_page(start);
34
35 smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, start + PAGE_SIZE);
36 smp_unlock_cache(flags);
37}
38EXPORT_SYMBOL(flush_icache_page);
39
40
41
42
43
44
45
46
47
48
49
50static void flush_icache_page_range(unsigned long start, unsigned long end)
51{
52 unsigned long addr, size, off;
53 struct page *page;
54 pgd_t *pgd;
55 pud_t *pud;
56 pmd_t *pmd;
57 pte_t *ppte, pte;
58
59
60 off = start & ~PAGE_MASK;
61 size = end - start;
62
63
64
65 pgd = pgd_offset(current->mm, start);
66 if (!pgd || !pgd_val(*pgd))
67 return;
68
69 pud = pud_offset(pgd, start);
70 if (!pud || !pud_val(*pud))
71 return;
72
73 pmd = pmd_offset(pud, start);
74 if (!pmd || !pmd_val(*pmd))
75 return;
76
77 ppte = pte_offset_map(pmd, start);
78 if (!ppte)
79 return;
80 pte = *ppte;
81 pte_unmap(ppte);
82
83 if (pte_none(pte))
84 return;
85
86 page = pte_page(pte);
87 if (!page)
88 return;
89
90 addr = page_to_phys(page);
91
92
93
94 mn10300_local_dcache_flush_range2(addr + off, size);
95 mn10300_local_icache_inv_range2(addr + off, size);
96 smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, end);
97}
98
99
100
101
102
103
104
105
106
107
108void flush_icache_range(unsigned long start, unsigned long end)
109{
110 unsigned long start_page, end_page;
111 unsigned long flags;
112
113 flags = smp_lock_cache();
114
115 if (end > 0x80000000UL) {
116
117 if (end > 0xa0000000UL) {
118 end = 0xa0000000UL;
119 if (start >= end)
120 goto done;
121 }
122
123
124
125
126 start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
127 mn10300_local_dcache_flush_range(start_page, end);
128 mn10300_local_icache_inv_range(start_page, end);
129 smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start_page, end);
130 if (start_page == start)
131 goto done;
132 end = start_page;
133 }
134
135 start_page = start & PAGE_MASK;
136 end_page = (end - 1) & PAGE_MASK;
137
138 if (start_page == end_page) {
139
140 flush_icache_page_range(start, end);
141 } else if (start_page + 1 == end_page) {
142
143 flush_icache_page_range(start, end_page);
144 flush_icache_page_range(end_page, end);
145 } else {
146
147 mn10300_dcache_flush();
148 mn10300_icache_inv();
149 smp_cache_call(SMP_IDCACHE_INV_FLUSH, 0, 0);
150 }
151
152done:
153 smp_unlock_cache(flags);
154}
155EXPORT_SYMBOL(flush_icache_range);
156