hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/arch/m68k/mm/kmap.c
....@@ -19,12 +19,10 @@
1919 #include <asm/setup.h>
2020 #include <asm/segment.h>
2121 #include <asm/page.h>
22
-#include <asm/pgalloc.h>
2322 #include <asm/io.h>
23
+#include <asm/tlbflush.h>
2424
2525 #undef DEBUG
26
-
27
-#define PTRTREESIZE (256*1024)
2826
2927 /*
3028 * For 040/060 we can use the virtual memory area like other architectures,
....@@ -50,9 +48,63 @@
5048
5149 #else
5250
53
-#define IO_SIZE (256*1024)
51
+#define IO_SIZE PMD_SIZE
5452
5553 static struct vm_struct *iolist;
54
+
55
+/*
56
+ * __free_io_area unmaps nearly everything, so be careful
57
+ * Currently it doesn't free pointer/page tables anymore but this
58
+ * wasn't used anyway and might be added later.
59
+ */
60
+static void __free_io_area(void *addr, unsigned long size)
61
+{
62
+ unsigned long virtaddr = (unsigned long)addr;
63
+ pgd_t *pgd_dir;
64
+ p4d_t *p4d_dir;
65
+ pud_t *pud_dir;
66
+ pmd_t *pmd_dir;
67
+ pte_t *pte_dir;
68
+
69
+ while ((long)size > 0) {
70
+ pgd_dir = pgd_offset_k(virtaddr);
71
+ p4d_dir = p4d_offset(pgd_dir, virtaddr);
72
+ pud_dir = pud_offset(p4d_dir, virtaddr);
73
+ if (pud_bad(*pud_dir)) {
74
+ printk("iounmap: bad pud(%08lx)\n", pud_val(*pud_dir));
75
+ pud_clear(pud_dir);
76
+ return;
77
+ }
78
+ pmd_dir = pmd_offset(pud_dir, virtaddr);
79
+
80
+#if CONFIG_PGTABLE_LEVELS == 3
81
+ if (CPU_IS_020_OR_030) {
82
+ int pmd_type = pmd_val(*pmd_dir) & _DESCTYPE_MASK;
83
+
84
+ if (pmd_type == _PAGE_PRESENT) {
85
+ pmd_clear(pmd_dir);
86
+ virtaddr += PMD_SIZE;
87
+ size -= PMD_SIZE;
88
+
89
+ } else if (pmd_type == 0)
90
+ continue;
91
+ }
92
+#endif
93
+
94
+ if (pmd_bad(*pmd_dir)) {
95
+ printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
96
+ pmd_clear(pmd_dir);
97
+ return;
98
+ }
99
+ pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
100
+
101
+ pte_val(*pte_dir) = 0;
102
+ virtaddr += PAGE_SIZE;
103
+ size -= PAGE_SIZE;
104
+ }
105
+
106
+ flush_tlb_all();
107
+}
56108
57109 static struct vm_struct *get_io_area(unsigned long size)
58110 {
....@@ -90,7 +142,7 @@
90142 if (tmp->addr == addr) {
91143 *p = tmp->next;
92144 /* remove gap added in get_io_area() */
93
- __iounmap(tmp->addr, tmp->size - IO_SIZE);
145
+ __free_io_area(tmp->addr, tmp->size - IO_SIZE);
94146 kfree(tmp);
95147 return;
96148 }
....@@ -110,6 +162,8 @@
110162 unsigned long virtaddr, retaddr;
111163 long offset;
112164 pgd_t *pgd_dir;
165
+ p4d_t *p4d_dir;
166
+ pud_t *pud_dir;
113167 pmd_t *pmd_dir;
114168 pte_t *pte_dir;
115169
....@@ -192,22 +246,27 @@
192246
193247 while ((long)size > 0) {
194248 #ifdef DEBUG
195
- if (!(virtaddr & (PTRTREESIZE-1)))
249
+ if (!(virtaddr & (PMD_SIZE-1)))
196250 printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
197251 #endif
198252 pgd_dir = pgd_offset_k(virtaddr);
199
- pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
253
+ p4d_dir = p4d_offset(pgd_dir, virtaddr);
254
+ pud_dir = pud_offset(p4d_dir, virtaddr);
255
+ pmd_dir = pmd_alloc(&init_mm, pud_dir, virtaddr);
200256 if (!pmd_dir) {
201257 printk("ioremap: no mem for pmd_dir\n");
202258 return NULL;
203259 }
204260
261
+#if CONFIG_PGTABLE_LEVELS == 3
205262 if (CPU_IS_020_OR_030) {
206
- pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
207
- physaddr += PTRTREESIZE;
208
- virtaddr += PTRTREESIZE;
209
- size -= PTRTREESIZE;
210
- } else {
263
+ pmd_val(*pmd_dir) = physaddr;
264
+ physaddr += PMD_SIZE;
265
+ virtaddr += PMD_SIZE;
266
+ size -= PMD_SIZE;
267
+ } else
268
+#endif
269
+ {
211270 pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
212271 if (!pte_dir) {
213272 printk("ioremap: no mem for pte_dir\n");
....@@ -250,55 +309,6 @@
250309 EXPORT_SYMBOL(iounmap);
251310
252311 /*
253
- * __iounmap unmaps nearly everything, so be careful
254
- * Currently it doesn't free pointer/page tables anymore but this
255
- * wasn't used anyway and might be added later.
256
- */
257
-void __iounmap(void *addr, unsigned long size)
258
-{
259
- unsigned long virtaddr = (unsigned long)addr;
260
- pgd_t *pgd_dir;
261
- pmd_t *pmd_dir;
262
- pte_t *pte_dir;
263
-
264
- while ((long)size > 0) {
265
- pgd_dir = pgd_offset_k(virtaddr);
266
- if (pgd_bad(*pgd_dir)) {
267
- printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
268
- pgd_clear(pgd_dir);
269
- return;
270
- }
271
- pmd_dir = pmd_offset(pgd_dir, virtaddr);
272
-
273
- if (CPU_IS_020_OR_030) {
274
- int pmd_off = (virtaddr/PTRTREESIZE) & 15;
275
- int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
276
-
277
- if (pmd_type == _PAGE_PRESENT) {
278
- pmd_dir->pmd[pmd_off] = 0;
279
- virtaddr += PTRTREESIZE;
280
- size -= PTRTREESIZE;
281
- continue;
282
- } else if (pmd_type == 0)
283
- continue;
284
- }
285
-
286
- if (pmd_bad(*pmd_dir)) {
287
- printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
288
- pmd_clear(pmd_dir);
289
- return;
290
- }
291
- pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
292
-
293
- pte_val(*pte_dir) = 0;
294
- virtaddr += PAGE_SIZE;
295
- size -= PAGE_SIZE;
296
- }
297
-
298
- flush_tlb_all();
299
-}
300
-
301
-/*
302312 * Set new cache mode for some kernel address space.
303313 * The caller must push data for that range itself, if such data may already
304314 * be in the cache.
....@@ -307,6 +317,8 @@
307317 {
308318 unsigned long virtaddr = (unsigned long)addr;
309319 pgd_t *pgd_dir;
320
+ p4d_t *p4d_dir;
321
+ pud_t *pud_dir;
310322 pmd_t *pmd_dir;
311323 pte_t *pte_dir;
312324
....@@ -341,24 +353,27 @@
341353
342354 while ((long)size > 0) {
343355 pgd_dir = pgd_offset_k(virtaddr);
344
- if (pgd_bad(*pgd_dir)) {
345
- printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
346
- pgd_clear(pgd_dir);
356
+ p4d_dir = p4d_offset(pgd_dir, virtaddr);
357
+ pud_dir = pud_offset(p4d_dir, virtaddr);
358
+ if (pud_bad(*pud_dir)) {
359
+ printk("iocachemode: bad pud(%08lx)\n", pud_val(*pud_dir));
360
+ pud_clear(pud_dir);
347361 return;
348362 }
349
- pmd_dir = pmd_offset(pgd_dir, virtaddr);
363
+ pmd_dir = pmd_offset(pud_dir, virtaddr);
350364
365
+#if CONFIG_PGTABLE_LEVELS == 3
351366 if (CPU_IS_020_OR_030) {
352
- int pmd_off = (virtaddr/PTRTREESIZE) & 15;
367
+ unsigned long pmd = pmd_val(*pmd_dir);
353368
354
- if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
355
- pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
356
- _CACHEMASK040) | cmode;
357
- virtaddr += PTRTREESIZE;
358
- size -= PTRTREESIZE;
369
+ if ((pmd & _DESCTYPE_MASK) == _PAGE_PRESENT) {
370
+ *pmd_dir = __pmd((pmd & _CACHEMASK040) | cmode);
371
+ virtaddr += PMD_SIZE;
372
+ size -= PMD_SIZE;
359373 continue;
360374 }
361375 }
376
+#endif
362377
363378 if (pmd_bad(*pmd_dir)) {
364379 printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));