diff options
-rw-r--r-- | arch/m68k/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/m68k/mm/cache.c | 118 | ||||
-rw-r--r-- | arch/m68k/mm/memory.c | 104 | ||||
-rw-r--r-- | include/asm-m68k/cacheflush.h | 31 |
4 files changed, 137 insertions, 118 deletions
diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile index 90f1c735c110..5eaa43c4cb3c 100644 --- a/arch/m68k/mm/Makefile +++ b/arch/m68k/mm/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the linux m68k-specific parts of the memory manager. | 2 | # Makefile for the linux m68k-specific parts of the memory manager. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := init.o fault.o hwtest.o | 5 | obj-y := cache.o init.o fault.o hwtest.o |
6 | 6 | ||
7 | obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o | 7 | obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o |
8 | obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o | 8 | obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o |
diff --git a/arch/m68k/mm/cache.c b/arch/m68k/mm/cache.c new file mode 100644 index 000000000000..5437fff5fe07 --- /dev/null +++ b/arch/m68k/mm/cache.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/mm/cache.c | ||
3 | * | ||
4 | * Instruction cache handling | ||
5 | * | ||
6 | * Copyright (C) 1995 Hamish Macdonald | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <asm/pgalloc.h> | ||
11 | #include <asm/traps.h> | ||
12 | |||
13 | |||
14 | static unsigned long virt_to_phys_slow(unsigned long vaddr) | ||
15 | { | ||
16 | if (CPU_IS_060) { | ||
17 | unsigned long paddr; | ||
18 | |||
19 | /* The PLPAR instruction causes an access error if the translation | ||
20 | * is not possible. To catch this we use the same exception mechanism | ||
21 | * as for user space accesses in <asm/uaccess.h>. */ | ||
22 | asm volatile (".chip 68060\n" | ||
23 | "1: plpar (%0)\n" | ||
24 | ".chip 68k\n" | ||
25 | "2:\n" | ||
26 | ".section .fixup,\"ax\"\n" | ||
27 | " .even\n" | ||
28 | "3: sub.l %0,%0\n" | ||
29 | " jra 2b\n" | ||
30 | ".previous\n" | ||
31 | ".section __ex_table,\"a\"\n" | ||
32 | " .align 4\n" | ||
33 | " .long 1b,3b\n" | ||
34 | ".previous" | ||
35 | : "=a" (paddr) | ||
36 | : "0" (vaddr)); | ||
37 | return paddr; | ||
38 | } else if (CPU_IS_040) { | ||
39 | unsigned long mmusr; | ||
40 | |||
41 | asm volatile (".chip 68040\n\t" | ||
42 | "ptestr (%1)\n\t" | ||
43 | "movec %%mmusr, %0\n\t" | ||
44 | ".chip 68k" | ||
45 | : "=r" (mmusr) | ||
46 | : "a" (vaddr)); | ||
47 | |||
48 | if (mmusr & MMU_R_040) | ||
49 | return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK); | ||
50 | } else { | ||
51 | unsigned short mmusr; | ||
52 | unsigned long *descaddr; | ||
53 | |||
54 | asm volatile ("ptestr %3,%2@,#7,%0\n\t" | ||
55 | "pmove %%psr,%1@" | ||
56 | : "=a&" (descaddr) | ||
57 | : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg)); | ||
58 | if (mmusr & (MMU_I|MMU_B|MMU_L)) | ||
59 | return 0; | ||
60 | descaddr = phys_to_virt((unsigned long)descaddr); | ||
61 | switch (mmusr & MMU_NUM) { | ||
62 | case 1: | ||
63 | return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff); | ||
64 | case 2: | ||
65 | return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff); | ||
66 | case 3: | ||
67 | return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK); | ||
68 | } | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /* Push n pages at kernel virtual address and clear the icache */ | ||
74 | /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ | ||
75 | void flush_icache_range(unsigned long address, unsigned long endaddr) | ||
76 | { | ||
77 | |||
78 | if (CPU_IS_040_OR_060) { | ||
79 | address &= PAGE_MASK; | ||
80 | |||
81 | do { | ||
82 | asm volatile ("nop\n\t" | ||
83 | ".chip 68040\n\t" | ||
84 | "cpushp %%bc,(%0)\n\t" | ||
85 | ".chip 68k" | ||
86 | : : "a" (virt_to_phys_slow(address))); | ||
87 | address += PAGE_SIZE; | ||
88 | } while (address < endaddr); | ||
89 | } else { | ||
90 | unsigned long tmp; | ||
91 | asm volatile ("movec %%cacr,%0\n\t" | ||
92 | "orw %1,%0\n\t" | ||
93 | "movec %0,%%cacr" | ||
94 | : "=&d" (tmp) | ||
95 | : "di" (FLUSH_I)); | ||
96 | } | ||
97 | } | ||
98 | EXPORT_SYMBOL(flush_icache_range); | ||
99 | |||
100 | void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, | ||
101 | unsigned long addr, int len) | ||
102 | { | ||
103 | if (CPU_IS_040_OR_060) { | ||
104 | asm volatile ("nop\n\t" | ||
105 | ".chip 68040\n\t" | ||
106 | "cpushp %%bc,(%0)\n\t" | ||
107 | ".chip 68k" | ||
108 | : : "a" (page_to_phys(page))); | ||
109 | } else { | ||
110 | unsigned long tmp; | ||
111 | asm volatile ("movec %%cacr,%0\n\t" | ||
112 | "orw %1,%0\n\t" | ||
113 | "movec %0,%%cacr" | ||
114 | : "=&d" (tmp) | ||
115 | : "di" (FLUSH_I)); | ||
116 | } | ||
117 | } | ||
118 | |||
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index 1453a6013721..559942ce0e1e 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c | |||
@@ -354,110 +354,6 @@ void cache_push (unsigned long paddr, int len) | |||
354 | #endif | 354 | #endif |
355 | } | 355 | } |
356 | 356 | ||
357 | static unsigned long virt_to_phys_slow(unsigned long vaddr) | ||
358 | { | ||
359 | if (CPU_IS_060) { | ||
360 | mm_segment_t fs = get_fs(); | ||
361 | unsigned long paddr; | ||
362 | |||
363 | set_fs(get_ds()); | ||
364 | |||
365 | /* The PLPAR instruction causes an access error if the translation | ||
366 | * is not possible. To catch this we use the same exception mechanism | ||
367 | * as for user space accesses in <asm/uaccess.h>. */ | ||
368 | asm volatile (".chip 68060\n" | ||
369 | "1: plpar (%0)\n" | ||
370 | ".chip 68k\n" | ||
371 | "2:\n" | ||
372 | ".section .fixup,\"ax\"\n" | ||
373 | " .even\n" | ||
374 | "3: sub.l %0,%0\n" | ||
375 | " jra 2b\n" | ||
376 | ".previous\n" | ||
377 | ".section __ex_table,\"a\"\n" | ||
378 | " .align 4\n" | ||
379 | " .long 1b,3b\n" | ||
380 | ".previous" | ||
381 | : "=a" (paddr) | ||
382 | : "0" (vaddr)); | ||
383 | set_fs(fs); | ||
384 | return paddr; | ||
385 | } else if (CPU_IS_040) { | ||
386 | mm_segment_t fs = get_fs(); | ||
387 | unsigned long mmusr; | ||
388 | |||
389 | set_fs(get_ds()); | ||
390 | |||
391 | asm volatile (".chip 68040\n\t" | ||
392 | "ptestr (%1)\n\t" | ||
393 | "movec %%mmusr, %0\n\t" | ||
394 | ".chip 68k" | ||
395 | : "=r" (mmusr) | ||
396 | : "a" (vaddr)); | ||
397 | set_fs(fs); | ||
398 | |||
399 | if (mmusr & MMU_R_040) | ||
400 | return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK); | ||
401 | } else { | ||
402 | unsigned short mmusr; | ||
403 | unsigned long *descaddr; | ||
404 | |||
405 | asm volatile ("ptestr #5,%2@,#7,%0\n\t" | ||
406 | "pmove %%psr,%1@" | ||
407 | : "=a&" (descaddr) | ||
408 | : "a" (&mmusr), "a" (vaddr)); | ||
409 | if (mmusr & (MMU_I|MMU_B|MMU_L)) | ||
410 | return 0; | ||
411 | descaddr = phys_to_virt((unsigned long)descaddr); | ||
412 | switch (mmusr & MMU_NUM) { | ||
413 | case 1: | ||
414 | return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff); | ||
415 | case 2: | ||
416 | return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff); | ||
417 | case 3: | ||
418 | return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK); | ||
419 | } | ||
420 | } | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | /* Push n pages at kernel virtual address and clear the icache */ | ||
425 | /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ | ||
426 | void flush_icache_range(unsigned long address, unsigned long endaddr) | ||
427 | { | ||
428 | if (CPU_IS_040_OR_060) { | ||
429 | address &= PAGE_MASK; | ||
430 | |||
431 | if (address >= PAGE_OFFSET && address < (unsigned long)high_memory) { | ||
432 | do { | ||
433 | asm volatile ("nop\n\t" | ||
434 | ".chip 68040\n\t" | ||
435 | "cpushp %%bc,(%0)\n\t" | ||
436 | ".chip 68k" | ||
437 | : : "a" (virt_to_phys((void *)address))); | ||
438 | address += PAGE_SIZE; | ||
439 | } while (address < endaddr); | ||
440 | } else { | ||
441 | do { | ||
442 | asm volatile ("nop\n\t" | ||
443 | ".chip 68040\n\t" | ||
444 | "cpushp %%bc,(%0)\n\t" | ||
445 | ".chip 68k" | ||
446 | : : "a" (virt_to_phys_slow(address))); | ||
447 | address += PAGE_SIZE; | ||
448 | } while (address < endaddr); | ||
449 | } | ||
450 | } else { | ||
451 | unsigned long tmp; | ||
452 | asm volatile ("movec %%cacr,%0\n\t" | ||
453 | "orw %1,%0\n\t" | ||
454 | "movec %0,%%cacr" | ||
455 | : "=&d" (tmp) | ||
456 | : "di" (FLUSH_I)); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | |||
461 | #ifndef CONFIG_SINGLE_MEMORY_CHUNK | 357 | #ifndef CONFIG_SINGLE_MEMORY_CHUNK |
462 | int mm_end_of_chunk (unsigned long addr, int len) | 358 | int mm_end_of_chunk (unsigned long addr, int len) |
463 | { | 359 | { |
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h index e4773946f10d..8aba971b1368 100644 --- a/include/asm-m68k/cacheflush.h +++ b/include/asm-m68k/cacheflush.h | |||
@@ -130,20 +130,25 @@ static inline void __flush_page_to_ram(void *vaddr) | |||
130 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 130 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
131 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 131 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
132 | #define flush_icache_page(vma, page) __flush_page_to_ram(page_address(page)) | 132 | #define flush_icache_page(vma, page) __flush_page_to_ram(page_address(page)) |
133 | #define flush_icache_user_range(vma,pg,adr,len) do { } while (0) | ||
134 | |||
135 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | ||
136 | do { \ | ||
137 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | ||
138 | memcpy(dst, src, len); \ | ||
139 | } while (0) | ||
140 | |||
141 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | ||
142 | do { \ | ||
143 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | ||
144 | memcpy(dst, src, len); \ | ||
145 | } while (0) | ||
146 | 133 | ||
134 | extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, | ||
135 | unsigned long addr, int len); | ||
147 | extern void flush_icache_range(unsigned long address, unsigned long endaddr); | 136 | extern void flush_icache_range(unsigned long address, unsigned long endaddr); |
148 | 137 | ||
138 | static inline void copy_to_user_page(struct vm_area_struct *vma, | ||
139 | struct page *page, unsigned long vaddr, | ||
140 | void *dst, void *src, int len) | ||
141 | { | ||
142 | flush_cache_page(vma, vaddr, page_to_pfn(page)); | ||
143 | memcpy(dst, src, len); | ||
144 | flush_icache_user_range(vma, page, vaddr, len); | ||
145 | } | ||
146 | static inline void copy_from_user_page(struct vm_area_struct *vma, | ||
147 | struct page *page, unsigned long vaddr, | ||
148 | void *dst, void *src, int len) | ||
149 | { | ||
150 | flush_cache_page(vma, vaddr, page_to_pfn(page)); | ||
151 | memcpy(dst, src, len); | ||
152 | } | ||
153 | |||
149 | #endif /* _M68K_CACHEFLUSH_H */ | 154 | #endif /* _M68K_CACHEFLUSH_H */ |