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>
This commit is contained in:
Markos Chandras 2014-01-07 16:20:22 +00:00 committed by Ralf Baechle
parent cf62a8b813
commit cd26cb41ec
2 changed files with 83 additions and 0 deletions

View File

@ -51,6 +51,12 @@ EXPORT_SYMBOL(copy_page);
*/ */
EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__copy_user);
EXPORT_SYMBOL(__copy_user_inatomic); EXPORT_SYMBOL(__copy_user_inatomic);
#ifdef CONFIG_EVA
EXPORT_SYMBOL(__copy_from_user_eva);
EXPORT_SYMBOL(__copy_in_user_eva);
EXPORT_SYMBOL(__copy_to_user_eva);
EXPORT_SYMBOL(__copy_user_inatomic_eva);
#endif
EXPORT_SYMBOL(__bzero); EXPORT_SYMBOL(__bzero);
EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm); EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
EXPORT_SYMBOL(__strncpy_from_kernel_asm); EXPORT_SYMBOL(__strncpy_from_kernel_asm);

View File

@ -114,7 +114,24 @@
.section __ex_table,"a"; \ .section __ex_table,"a"; \
PTR 9b, handler; \ PTR 9b, handler; \
.previous; \ .previous; \
/* This is assembled in EVA mode */ \
.else; \
/* If loading from user or storing to user */ \
.if ((\from == USEROP) && (type == LD_INSN)) || \
((\to == USEROP) && (type == ST_INSN)); \
9: __BUILD_EVA_INSN(insn##e, reg, addr); \
.section __ex_table,"a"; \
PTR 9b, handler; \
.previous; \
.else; \
/* \
* Still in EVA, but no need for \
* exception handler or EVA insn \
*/ \
insn reg, addr; \
.endif; \
.endif .endif
/* /*
* Only on the 64-bit kernel we can made use of 64-bit registers. * Only on the 64-bit kernel we can made use of 64-bit registers.
*/ */
@ -186,6 +203,22 @@
#define _PREF(hint, addr, type) \ #define _PREF(hint, addr, type) \
.if \mode == LEGACY_MODE; \ .if \mode == LEGACY_MODE; \
PREF(hint, addr); \ PREF(hint, addr); \
.else; \
.if ((\from == USEROP) && (type == SRC_PREFETCH)) || \
((\to == USEROP) && (type == DST_PREFETCH)); \
/* \
* PREFE has only 9 bits for the offset \
* compared to PREF which has 16, so it may \
* need to use the $at register but this \
* register should remain intact because it's \
* used later on. Therefore use $v1. \
*/ \
.set at=v1; \
PREFE(hint, addr); \
.set noat; \
.else; \
PREF(hint, addr); \
.endif; \
.endif .endif
#define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH) #define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH)
@ -636,3 +669,47 @@ FEXPORT(__copy_user)
__copy_user_common: __copy_user_common:
/* Legacy Mode, user <-> user */ /* Legacy Mode, user <-> user */
__BUILD_COPY_USER LEGACY_MODE USEROP USEROP __BUILD_COPY_USER LEGACY_MODE USEROP USEROP
#ifdef CONFIG_EVA
/*
* For EVA we need distinct symbols for reading and writing to user space.
* This is because we need to use specific EVA instructions to perform the
* virtual <-> physical translation when a virtual address is actually in user
* space
*/
LEAF(__copy_user_inatomic_eva)
b __copy_from_user_common
li t6, 1
END(__copy_user_inatomic_eva)
/*
* __copy_from_user (EVA)
*/
LEAF(__copy_from_user_eva)
li t6, 0 /* not inatomic */
__copy_from_user_common:
__BUILD_COPY_USER EVA_MODE USEROP KERNELOP
END(__copy_from_user_eva)
/*
* __copy_to_user (EVA)
*/
LEAF(__copy_to_user_eva)
__BUILD_COPY_USER EVA_MODE KERNELOP USEROP
END(__copy_to_user_eva)
/*
* __copy_in_user (EVA)
*/
LEAF(__copy_in_user_eva)
__BUILD_COPY_USER EVA_MODE USEROP USEROP
END(__copy_in_user_eva)
#endif