aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lib
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2014-01-07 11:20:22 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-03-26 18:09:14 -0400
commitcd26cb41ece49ce0dd0f43d88f4d3386ca42a825 (patch)
tree8b19eb812d21611ef0e458dd59ef3159d6fcaec8 /arch/mips/lib
parentcf62a8b8134dd37ab365bfe8b972a7ebb1100110 (diff)
MIPS: lib: memcpy: Add EVA support
Add copy_{to,from,in}_user when the CPU operates in EVA mode. This is necessary so the EVA specific instructions can be used to perform the virtual to physical translation for user space addresses. We will use the non-EVA functions to read from kernel if needed. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Diffstat (limited to 'arch/mips/lib')
-rw-r--r--arch/mips/lib/memcpy.S77
1 files changed, 77 insertions, 0 deletions
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index d630a28a118b..c17ef80cf65a 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -114,7 +114,24 @@
114 .section __ex_table,"a"; \ 114 .section __ex_table,"a"; \
115 PTR 9b, handler; \ 115 PTR 9b, handler; \
116 .previous; \ 116 .previous; \
117 /* This is assembled in EVA mode */ \
118 .else; \
119 /* If loading from user or storing to user */ \
120 .if ((\from == USEROP) && (type == LD_INSN)) || \
121 ((\to == USEROP) && (type == ST_INSN)); \
1229: __BUILD_EVA_INSN(insn##e, reg, addr); \
123 .section __ex_table,"a"; \
124 PTR 9b, handler; \
125 .previous; \
126 .else; \
127 /* \
128 * Still in EVA, but no need for \
129 * exception handler or EVA insn \
130 */ \
131 insn reg, addr; \
132 .endif; \
117 .endif 133 .endif
134
118/* 135/*
119 * Only on the 64-bit kernel we can made use of 64-bit registers. 136 * Only on the 64-bit kernel we can made use of 64-bit registers.
120 */ 137 */
@@ -186,6 +203,22 @@
186#define _PREF(hint, addr, type) \ 203#define _PREF(hint, addr, type) \
187 .if \mode == LEGACY_MODE; \ 204 .if \mode == LEGACY_MODE; \
188 PREF(hint, addr); \ 205 PREF(hint, addr); \
206 .else; \
207 .if ((\from == USEROP) && (type == SRC_PREFETCH)) || \
208 ((\to == USEROP) && (type == DST_PREFETCH)); \
209 /* \
210 * PREFE has only 9 bits for the offset \
211 * compared to PREF which has 16, so it may \
212 * need to use the $at register but this \
213 * register should remain intact because it's \
214 * used later on. Therefore use $v1. \
215 */ \
216 .set at=v1; \
217 PREFE(hint, addr); \
218 .set noat; \
219 .else; \
220 PREF(hint, addr); \
221 .endif; \
189 .endif 222 .endif
190 223
191#define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH) 224#define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH)
@@ -636,3 +669,47 @@ FEXPORT(__copy_user)
636__copy_user_common: 669__copy_user_common:
637 /* Legacy Mode, user <-> user */ 670 /* Legacy Mode, user <-> user */
638 __BUILD_COPY_USER LEGACY_MODE USEROP USEROP 671 __BUILD_COPY_USER LEGACY_MODE USEROP USEROP
672
673#ifdef CONFIG_EVA
674
675/*
676 * For EVA we need distinct symbols for reading and writing to user space.
677 * This is because we need to use specific EVA instructions to perform the
678 * virtual <-> physical translation when a virtual address is actually in user
679 * space
680 */
681
682LEAF(__copy_user_inatomic_eva)
683 b __copy_from_user_common
684 li t6, 1
685 END(__copy_user_inatomic_eva)
686
687/*
688 * __copy_from_user (EVA)
689 */
690
691LEAF(__copy_from_user_eva)
692 li t6, 0 /* not inatomic */
693__copy_from_user_common:
694 __BUILD_COPY_USER EVA_MODE USEROP KERNELOP
695END(__copy_from_user_eva)
696
697
698
699/*
700 * __copy_to_user (EVA)
701 */
702
703LEAF(__copy_to_user_eva)
704__BUILD_COPY_USER EVA_MODE KERNELOP USEROP
705END(__copy_to_user_eva)
706
707/*
708 * __copy_in_user (EVA)
709 */
710
711LEAF(__copy_in_user_eva)
712__BUILD_COPY_USER EVA_MODE USEROP USEROP
713END(__copy_in_user_eva)
714
715#endif