Skip to content

Commit d5d797d

Browse files
author
Peter Zijlstra
committed
x86/usercopy: Remove .fixup usage
Typically usercopy does whole word copies followed by a number of byte copies to finish the tail. This means that on exception it needs to compute the remaining length as: words*sizeof(long) + bytes. Create a new extable handler to do just this. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Josh Poimboeuf <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 13e4bf1 commit d5d797d

File tree

4 files changed

+22
-28
lines changed

4 files changed

+22
-28
lines changed

arch/x86/include/asm/extable_fixup_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,9 @@
5050

5151
#define EX_TYPE_FAULT_SGX 18
5252

53+
#define EX_TYPE_UCOPY_LEN 19 /* cx := reg + imm*cx */
54+
#define EX_TYPE_UCOPY_LEN1 (EX_TYPE_UCOPY_LEN | EX_DATA_IMM(1))
55+
#define EX_TYPE_UCOPY_LEN4 (EX_TYPE_UCOPY_LEN | EX_DATA_IMM(4))
56+
#define EX_TYPE_UCOPY_LEN8 (EX_TYPE_UCOPY_LEN | EX_DATA_IMM(8))
57+
5358
#endif

arch/x86/lib/usercopy_32.c

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,7 @@ do { \
4242
" movl %2,%0\n" \
4343
"1: rep; stosb\n" \
4444
"2: " ASM_CLAC "\n" \
45-
".section .fixup,\"ax\"\n" \
46-
"3: lea 0(%2,%0,4),%0\n" \
47-
" jmp 2b\n" \
48-
".previous\n" \
49-
_ASM_EXTABLE_UA(0b, 3b) \
45+
_ASM_EXTABLE_TYPE_REG(0b, 2b, EX_TYPE_UCOPY_LEN4, %2) \
5046
_ASM_EXTABLE_UA(1b, 2b) \
5147
: "=&c"(size), "=&D" (__d0) \
5248
: "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \
@@ -148,10 +144,6 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size)
148144
"36: movl %%eax, %0\n"
149145
"37: rep; movsb\n"
150146
"100:\n"
151-
".section .fixup,\"ax\"\n"
152-
"101: lea 0(%%eax,%0,4),%0\n"
153-
" jmp 100b\n"
154-
".previous\n"
155147
_ASM_EXTABLE_UA(1b, 100b)
156148
_ASM_EXTABLE_UA(2b, 100b)
157149
_ASM_EXTABLE_UA(3b, 100b)
@@ -189,7 +181,7 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size)
189181
_ASM_EXTABLE_UA(35b, 100b)
190182
_ASM_EXTABLE_UA(36b, 100b)
191183
_ASM_EXTABLE_UA(37b, 100b)
192-
_ASM_EXTABLE_UA(99b, 101b)
184+
_ASM_EXTABLE_TYPE_REG(99b, 100b, EX_TYPE_UCOPY_LEN4, %%eax)
193185
: "=&c"(size), "=&D" (d0), "=&S" (d1)
194186
: "1"(to), "2"(from), "0"(size)
195187
: "eax", "edx", "memory");
@@ -254,10 +246,6 @@ static unsigned long __copy_user_intel_nocache(void *to,
254246
" movl %%eax,%0\n"
255247
"7: rep; movsb\n"
256248
"8:\n"
257-
".section .fixup,\"ax\"\n"
258-
"9: lea 0(%%eax,%0,4),%0\n"
259-
" jmp 8b\n"
260-
".previous\n"
261249
_ASM_EXTABLE_UA(0b, 8b)
262250
_ASM_EXTABLE_UA(1b, 8b)
263251
_ASM_EXTABLE_UA(2b, 8b)
@@ -276,7 +264,7 @@ static unsigned long __copy_user_intel_nocache(void *to,
276264
_ASM_EXTABLE_UA(81b, 8b)
277265
_ASM_EXTABLE_UA(14b, 8b)
278266
_ASM_EXTABLE_UA(91b, 8b)
279-
_ASM_EXTABLE_UA(6b, 9b)
267+
_ASM_EXTABLE_TYPE_REG(6b, 8b, EX_TYPE_UCOPY_LEN4, %%eax)
280268
_ASM_EXTABLE_UA(7b, 8b)
281269
: "=&c"(size), "=&D" (d0), "=&S" (d1)
282270
: "1"(to), "2"(from), "0"(size)
@@ -314,14 +302,8 @@ do { \
314302
" movl %3,%0\n" \
315303
"1: rep; movsb\n" \
316304
"2:\n" \
317-
".section .fixup,\"ax\"\n" \
318-
"5: addl %3,%0\n" \
319-
" jmp 2b\n" \
320-
"3: lea 0(%3,%0,4),%0\n" \
321-
" jmp 2b\n" \
322-
".previous\n" \
323-
_ASM_EXTABLE_UA(4b, 5b) \
324-
_ASM_EXTABLE_UA(0b, 3b) \
305+
_ASM_EXTABLE_TYPE_REG(4b, 2b, EX_TYPE_UCOPY_LEN1, %3) \
306+
_ASM_EXTABLE_TYPE_REG(0b, 2b, EX_TYPE_UCOPY_LEN4, %3) \
325307
_ASM_EXTABLE_UA(1b, 2b) \
326308
: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
327309
: "3"(size), "0"(size), "1"(to), "2"(from) \

arch/x86/lib/usercopy_64.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,10 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
3535
" incq %[dst]\n"
3636
" decl %%ecx ; jnz 1b\n"
3737
"2:\n"
38-
".section .fixup,\"ax\"\n"
39-
"3: lea 0(%[size1],%[size8],8),%[size8]\n"
40-
" jmp 2b\n"
41-
".previous\n"
42-
_ASM_EXTABLE_UA(0b, 3b)
38+
39+
_ASM_EXTABLE_TYPE_REG(0b, 2b, EX_TYPE_UCOPY_LEN8, %[size1])
4340
_ASM_EXTABLE_UA(1b, 2b)
41+
4442
: [size8] "=&c"(size), [dst] "=&D" (__d0)
4543
: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr));
4644
clac();

arch/x86/mm/extable.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,13 @@ static bool ex_handler_imm_reg(const struct exception_table_entry *fixup,
145145
return ex_handler_default(fixup, regs);
146146
}
147147

148+
static bool ex_handler_ucopy_len(const struct exception_table_entry *fixup,
149+
struct pt_regs *regs, int trapnr, int reg, int imm)
150+
{
151+
regs->cx = imm * regs->cx + *pt_regs_nr(regs, reg);
152+
return ex_handler_uaccess(fixup, regs, trapnr);
153+
}
154+
148155
int ex_get_fixup_type(unsigned long ip)
149156
{
150157
const struct exception_table_entry *e = search_exception_tables(ip);
@@ -217,6 +224,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
217224
return ex_handler_imm_reg(e, regs, reg, imm);
218225
case EX_TYPE_FAULT_SGX:
219226
return ex_handler_sgx(e, regs, trapnr);
227+
case EX_TYPE_UCOPY_LEN:
228+
return ex_handler_ucopy_len(e, regs, trapnr, reg, imm);
220229
}
221230
BUG();
222231
}

0 commit comments

Comments
 (0)