diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-10-21 18:17:35 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-10-21 18:17:35 -0400 |
commit | f8829caee311207afbc882794bdc5aa0db5caf33 (patch) | |
tree | dbadd9fa746a1a4f091bc7e240ca8d787188a913 /include/asm-mips | |
parent | 224dc50ece1b40f8cff5ecadd42a6b2691e231de (diff) |
[MIPS] Fix aliasing bug in copy_to_user_page / copy_from_user_page
The current implementation uses a sequence of a cacheflush and a copy.
This is racy in case of a multithreaded debuggee and renders GDB
virtually unusable.
Aside this fixes a performance hog rendering access to /proc/cmdline very
slow and resulting in a enough cache stalls for the 34K AP/SP programming
model to make the bare metal code on the non-Linux VPE miss RT deadlines.
The main part of this patch was originally written by Ralf Baechle;
Atushi Nemoto did the the debugging.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include/asm-mips')
-rw-r--r-- | include/asm-mips/cacheflush.h | 19 | ||||
-rw-r--r-- | include/asm-mips/fixmap.h | 14 |
2 files changed, 15 insertions, 18 deletions
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h index 9ab59e2bb233..e3c9925876a3 100644 --- a/include/asm-mips/cacheflush.h +++ b/include/asm-mips/cacheflush.h | |||
@@ -55,24 +55,13 @@ extern void (*flush_icache_range)(unsigned long start, unsigned long end); | |||
55 | #define flush_cache_vmap(start, end) flush_cache_all() | 55 | #define flush_cache_vmap(start, end) flush_cache_all() |
56 | #define flush_cache_vunmap(start, end) flush_cache_all() | 56 | #define flush_cache_vunmap(start, end) flush_cache_all() |
57 | 57 | ||
58 | static inline void copy_to_user_page(struct vm_area_struct *vma, | 58 | extern void copy_to_user_page(struct vm_area_struct *vma, |
59 | struct page *page, unsigned long vaddr, void *dst, const void *src, | 59 | struct page *page, unsigned long vaddr, void *dst, const void *src, |
60 | unsigned long len) | 60 | unsigned long len); |
61 | { | ||
62 | if (cpu_has_dc_aliases) | ||
63 | flush_cache_page(vma, vaddr, page_to_pfn(page)); | ||
64 | memcpy(dst, src, len); | ||
65 | __flush_icache_page(vma, page); | ||
66 | } | ||
67 | 61 | ||
68 | static inline void copy_from_user_page(struct vm_area_struct *vma, | 62 | extern void copy_from_user_page(struct vm_area_struct *vma, |
69 | struct page *page, unsigned long vaddr, void *dst, const void *src, | 63 | struct page *page, unsigned long vaddr, void *dst, const void *src, |
70 | unsigned long len) | 64 | unsigned long len); |
71 | { | ||
72 | if (cpu_has_dc_aliases) | ||
73 | flush_cache_page(vma, vaddr, page_to_pfn(page)); | ||
74 | memcpy(dst, src, len); | ||
75 | } | ||
76 | 65 | ||
77 | extern void (*flush_cache_sigtramp)(unsigned long addr); | 66 | extern void (*flush_cache_sigtramp)(unsigned long addr); |
78 | extern void (*flush_icache_all)(void); | 67 | extern void (*flush_icache_all)(void); |
diff --git a/include/asm-mips/fixmap.h b/include/asm-mips/fixmap.h index 6959bdb59310..02c8a13fc894 100644 --- a/include/asm-mips/fixmap.h +++ b/include/asm-mips/fixmap.h | |||
@@ -45,8 +45,16 @@ | |||
45 | * fix-mapped? | 45 | * fix-mapped? |
46 | */ | 46 | */ |
47 | enum fixed_addresses { | 47 | enum fixed_addresses { |
48 | #define FIX_N_COLOURS 8 | ||
49 | FIX_CMAP_BEGIN, | ||
50 | #ifdef CONFIG_MIPS_MT_SMTC | ||
51 | FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS), | ||
52 | #else | ||
53 | FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, | ||
54 | #endif | ||
48 | #ifdef CONFIG_HIGHMEM | 55 | #ifdef CONFIG_HIGHMEM |
49 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | 56 | /* reserved pte's for temporary kernel mappings */ |
57 | FIX_KMAP_BEGIN = FIX_CMAP_END + 1, | ||
50 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, | 58 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, |
51 | #endif | 59 | #endif |
52 | __end_of_fixed_addresses | 60 | __end_of_fixed_addresses |
@@ -70,9 +78,9 @@ extern void __set_fixmap (enum fixed_addresses idx, | |||
70 | * at the top of mem.. | 78 | * at the top of mem.. |
71 | */ | 79 | */ |
72 | #if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) | 80 | #if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) |
73 | #define FIXADDR_TOP (0xff000000UL - 0x2000) | 81 | #define FIXADDR_TOP ((unsigned long)(long)(int)(0xff000000 - 0x20000)) |
74 | #else | 82 | #else |
75 | #define FIXADDR_TOP (0xffffe000UL) | 83 | #define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) |
76 | #endif | 84 | #endif |
77 | #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | 85 | #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) |
78 | #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) | 86 | #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) |