diff options
Diffstat (limited to 'arch/mips/lib')
-rw-r--r-- | arch/mips/lib/memcpy.S | 77 |
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)); \ | ||
122 | 9: __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 | |||
682 | LEAF(__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 | |||
691 | LEAF(__copy_from_user_eva) | ||
692 | li t6, 0 /* not inatomic */ | ||
693 | __copy_from_user_common: | ||
694 | __BUILD_COPY_USER EVA_MODE USEROP KERNELOP | ||
695 | END(__copy_from_user_eva) | ||
696 | |||
697 | |||
698 | |||
699 | /* | ||
700 | * __copy_to_user (EVA) | ||
701 | */ | ||
702 | |||
703 | LEAF(__copy_to_user_eva) | ||
704 | __BUILD_COPY_USER EVA_MODE KERNELOP USEROP | ||
705 | END(__copy_to_user_eva) | ||
706 | |||
707 | /* | ||
708 | * __copy_in_user (EVA) | ||
709 | */ | ||
710 | |||
711 | LEAF(__copy_in_user_eva) | ||
712 | __BUILD_COPY_USER EVA_MODE USEROP USEROP | ||
713 | END(__copy_in_user_eva) | ||
714 | |||
715 | #endif | ||