Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] m68k: move cache functions into separate file

Move a few cache functions into its own file and fix flush_icache_range() so
it can handle both kernel and user addresses correctly (assuming context is
set correctly).

Turn copy_to_user_page/copy_from_user_page into inline functions and add a
missing cache flush.

Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Roman Zippel and committed by
Linus Torvalds
2855b970 69f447cf

+137 -118
+1 -1
arch/m68k/mm/Makefile
··· 2 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 7 obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o 8 8 obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
+118
arch/m68k/mm/cache.c
··· 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 +
-104
arch/m68k/mm/memory.c
··· 354 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 357 #ifndef CONFIG_SINGLE_MEMORY_CHUNK 462 358 int mm_end_of_chunk (unsigned long addr, int len) 463 359 {
+18 -13
include/asm-m68k/cacheflush.h
··· 130 130 #define flush_dcache_mmap_lock(mapping) do { } while (0) 131 131 #define flush_dcache_mmap_unlock(mapping) do { } while (0) 132 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 133 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 - 134 + extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, 135 + unsigned long addr, int len); 147 136 extern void flush_icache_range(unsigned long address, unsigned long endaddr); 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 + } 148 153 149 154 #endif /* _M68K_CACHEFLUSH_H */