Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Provide common bits of early_ioremap() support for architectures needing
4 : : * temporary mappings during boot before ioremap() is available.
5 : : *
6 : : * This is mostly a direct copy of the x86 early_ioremap implementation.
7 : : *
8 : : * (C) Copyright 1995 1996, 2014 Linus Torvalds
9 : : *
10 : : */
11 : : #include <linux/kernel.h>
12 : : #include <linux/init.h>
13 : : #include <linux/io.h>
14 : : #include <linux/module.h>
15 : : #include <linux/slab.h>
16 : : #include <linux/mm.h>
17 : : #include <linux/vmalloc.h>
18 : : #include <asm/fixmap.h>
19 : : #include <asm/early_ioremap.h>
20 : :
21 : : #ifdef CONFIG_MMU
22 : : static int early_ioremap_debug __initdata;
23 : :
24 : 0 : static int __init early_ioremap_debug_setup(char *str)
25 : : {
26 : 0 : early_ioremap_debug = 1;
27 : :
28 : 0 : return 0;
29 : : }
30 : : early_param("early_ioremap_debug", early_ioremap_debug_setup);
31 : :
32 : : static int after_paging_init __initdata;
33 : :
34 : 0 : pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,
35 : : unsigned long size,
36 : : pgprot_t prot)
37 : : {
38 : 0 : return prot;
39 : : }
40 : :
41 : 0 : void __init __weak early_ioremap_shutdown(void)
42 : : {
43 : 0 : }
44 : :
45 : 0 : void __init early_ioremap_reset(void)
46 : : {
47 : 0 : early_ioremap_shutdown();
48 : 0 : after_paging_init = 1;
49 : 0 : }
50 : :
51 : : /*
52 : : * Generally, ioremap() is available after paging_init() has been called.
53 : : * Architectures wanting to allow early_ioremap after paging_init() can
54 : : * define __late_set_fixmap and __late_clear_fixmap to do the right thing.
55 : : */
56 : : #ifndef __late_set_fixmap
57 : : static inline void __init __late_set_fixmap(enum fixed_addresses idx,
58 : : phys_addr_t phys, pgprot_t prot)
59 : : {
60 : : BUG();
61 : : }
62 : : #endif
63 : :
64 : : #ifndef __late_clear_fixmap
65 : : static inline void __init __late_clear_fixmap(enum fixed_addresses idx)
66 : : {
67 : : BUG();
68 : : }
69 : : #endif
70 : :
71 : : static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
72 : : static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
73 : : static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
74 : :
75 : 11 : void __init early_ioremap_setup(void)
76 : : {
77 : 11 : int i;
78 : :
79 [ + + ]: 99 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
80 [ - + - + ]: 88 : if (WARN_ON(prev_map[i]))
81 : : break;
82 : :
83 [ + + ]: 99 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
84 : 88 : slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
85 : 11 : }
86 : :
87 : 11 : static int __init check_early_ioremap_leak(void)
88 : : {
89 : 11 : int count = 0;
90 : 11 : int i;
91 : :
92 [ + + ]: 99 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
93 [ - + ]: 88 : if (prev_map[i])
94 : 0 : count++;
95 : :
96 [ - + - + ]: 11 : if (WARN(count, KERN_WARNING
97 : : "Debug warning: early ioremap leak of %d areas detected.\n"
98 : : "please boot with early_ioremap_debug and report the dmesg.\n",
99 : : count))
100 : 0 : return 1;
101 : : return 0;
102 : : }
103 : : late_initcall(check_early_ioremap_leak);
104 : :
105 : : static void __init __iomem *
106 : 20581 : __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
107 : : {
108 : 20581 : unsigned long offset;
109 : 20581 : resource_size_t last_addr;
110 : 20581 : unsigned int nrpages;
111 : 20581 : enum fixed_addresses idx;
112 : 20581 : int i, slot;
113 : :
114 [ - + ]: 20581 : WARN_ON(system_state >= SYSTEM_RUNNING);
115 : :
116 : : slot = -1;
117 [ + - ]: 20724 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
118 [ + + ]: 20724 : if (!prev_map[i]) {
119 : : slot = i;
120 : : break;
121 : : }
122 : : }
123 : :
124 [ - + + - ]: 20581 : if (WARN(slot < 0, "%s(%pa, %08lx) not found slot\n",
125 : : __func__, &phys_addr, size))
126 : : return NULL;
127 : :
128 : : /* Don't allow wraparound or zero size */
129 : 20581 : last_addr = phys_addr + size - 1;
130 [ + - + - : 41162 : if (WARN_ON(!size || last_addr < phys_addr))
- + + - ]
131 : : return NULL;
132 : :
133 : 20581 : prev_size[slot] = size;
134 : : /*
135 : : * Mappings have to be page-aligned
136 : : */
137 : 20581 : offset = offset_in_page(phys_addr);
138 : 20581 : phys_addr &= PAGE_MASK;
139 : 20581 : size = PAGE_ALIGN(last_addr + 1) - phys_addr;
140 : :
141 : : /*
142 : : * Mappings have to fit in the FIX_BTMAP area.
143 : : */
144 : 20581 : nrpages = size >> PAGE_SHIFT;
145 [ - + + - ]: 20581 : if (WARN_ON(nrpages > NR_FIX_BTMAPS))
146 : : return NULL;
147 : :
148 : : /*
149 : : * Ok, go for it..
150 : : */
151 : 20581 : idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
152 [ + + ]: 269566 : while (nrpages > 0) {
153 [ - + ]: 248985 : if (after_paging_init)
154 : 0 : __late_set_fixmap(idx, phys_addr, prot);
155 : : else
156 : 248985 : __early_set_fixmap(idx, phys_addr, prot);
157 : 248985 : phys_addr += PAGE_SIZE;
158 : 248985 : --idx;
159 : 248985 : --nrpages;
160 : : }
161 [ - + ]: 20581 : WARN(early_ioremap_debug, "%s(%pa, %08lx) [%d] => %08lx + %08lx\n",
162 : : __func__, &phys_addr, size, slot, offset, slot_virt[slot]);
163 : :
164 : 20581 : prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
165 : 20581 : return prev_map[slot];
166 : : }
167 : :
168 : 20581 : void __init early_iounmap(void __iomem *addr, unsigned long size)
169 : : {
170 : 20581 : unsigned long virt_addr;
171 : 20581 : unsigned long offset;
172 : 20581 : unsigned int nrpages;
173 : 20581 : enum fixed_addresses idx;
174 : 20581 : int i, slot;
175 : :
176 : 20581 : slot = -1;
177 [ + - ]: 20724 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
178 [ + + ]: 20724 : if (prev_map[i] == addr) {
179 : : slot = i;
180 : : break;
181 : : }
182 : : }
183 : :
184 [ - + + - ]: 20581 : if (WARN(slot < 0, "early_iounmap(%p, %08lx) not found slot\n",
185 : : addr, size))
186 : : return;
187 : :
188 [ - + + - ]: 20581 : if (WARN(prev_size[slot] != size,
189 : : "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
190 : : addr, size, slot, prev_size[slot]))
191 : : return;
192 : :
193 [ - + ]: 20581 : WARN(early_ioremap_debug, "early_iounmap(%p, %08lx) [%d]\n",
194 : : addr, size, slot);
195 : :
196 : 20581 : virt_addr = (unsigned long)addr;
197 [ - + + - ]: 20581 : if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)))
198 : : return;
199 : :
200 : 20581 : offset = offset_in_page(virt_addr);
201 : 20581 : nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
202 : :
203 : 20581 : idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
204 [ + + ]: 269566 : while (nrpages > 0) {
205 [ - + ]: 248985 : if (after_paging_init)
206 : 0 : __late_clear_fixmap(idx);
207 : : else
208 : 248985 : __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR);
209 : 248985 : --idx;
210 : 248985 : --nrpages;
211 : : }
212 : 20581 : prev_map[slot] = NULL;
213 : : }
214 : :
215 : : /* Remap an IO device */
216 : : void __init __iomem *
217 : 0 : early_ioremap(resource_size_t phys_addr, unsigned long size)
218 : : {
219 : 0 : return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO);
220 : : }
221 : :
222 : : /* Remap memory */
223 : : void __init *
224 : 20581 : early_memremap(resource_size_t phys_addr, unsigned long size)
225 : : {
226 : 20581 : pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size,
227 : 20581 : FIXMAP_PAGE_NORMAL);
228 : :
229 : 20581 : return (__force void *)__early_ioremap(phys_addr, size, prot);
230 : : }
231 : : #ifdef FIXMAP_PAGE_RO
232 : : void __init *
233 : 0 : early_memremap_ro(resource_size_t phys_addr, unsigned long size)
234 : : {
235 : 0 : pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size,
236 : 0 : FIXMAP_PAGE_RO);
237 : :
238 : 0 : return (__force void *)__early_ioremap(phys_addr, size, prot);
239 : : }
240 : : #endif
241 : :
242 : : #ifdef CONFIG_ARCH_USE_MEMREMAP_PROT
243 : : void __init *
244 : 0 : early_memremap_prot(resource_size_t phys_addr, unsigned long size,
245 : : unsigned long prot_val)
246 : : {
247 : 0 : return (__force void *)__early_ioremap(phys_addr, size,
248 : 0 : __pgprot(prot_val));
249 : : }
250 : : #endif
251 : :
252 : : #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)
253 : :
254 : 0 : void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
255 : : {
256 : 0 : unsigned long slop, clen;
257 : 0 : char *p;
258 : :
259 [ # # ]: 0 : while (size) {
260 : 0 : slop = offset_in_page(src);
261 : 0 : clen = size;
262 : 0 : if (clen > MAX_MAP_CHUNK - slop)
263 : : clen = MAX_MAP_CHUNK - slop;
264 : 0 : p = early_memremap(src & PAGE_MASK, clen + slop);
265 : 0 : memcpy(dest, p + slop, clen);
266 : 0 : early_memunmap(p, clen + slop);
267 : 0 : dest += clen;
268 : 0 : src += clen;
269 : 0 : size -= clen;
270 : : }
271 : 0 : }
272 : :
273 : : #else /* CONFIG_MMU */
274 : :
275 : : void __init __iomem *
276 : : early_ioremap(resource_size_t phys_addr, unsigned long size)
277 : : {
278 : : return (__force void __iomem *)phys_addr;
279 : : }
280 : :
281 : : /* Remap memory */
282 : : void __init *
283 : : early_memremap(resource_size_t phys_addr, unsigned long size)
284 : : {
285 : : return (void *)phys_addr;
286 : : }
287 : : void __init *
288 : : early_memremap_ro(resource_size_t phys_addr, unsigned long size)
289 : : {
290 : : return (void *)phys_addr;
291 : : }
292 : :
293 : : void __init early_iounmap(void __iomem *addr, unsigned long size)
294 : : {
295 : : }
296 : :
297 : : #endif /* CONFIG_MMU */
298 : :
299 : :
300 : 20581 : void __init early_memunmap(void *addr, unsigned long size)
301 : : {
302 : 20581 : early_iounmap((__force void __iomem *)addr, size);
303 : 20581 : }
|