forked from Minki/linux
powerpc/64: Copy as much as possible in __copy_tofrom_user
In __copy_tofrom_user, if we encounter an exception on a store, we stop copying and return the number of bytes not copied. However, if the store is wider than one byte and is to an unaligned address, it is possible that the store operand overlaps a page boundary and the exception occurred on the latter part of the store operand, meaning that it would be possible to copy a few more bytes. Since copy_to_user is generally expected to copy as much as possible, it would be better to copy those extra few bytes. This adds code to do that. Since this edge case is not performance-critical, the code has been written to be compact rather than as fast as possible. Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
2679f63fe5
commit
f8db2007ff
@ -379,8 +379,8 @@ stex; stb r0,0(r3)
|
|||||||
blr
|
blr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exception handlers for stores: we just need to work
|
* exception handlers for stores: we need to work out how many bytes
|
||||||
* out how many bytes weren't copied
|
* weren't copied, and we may need to copy some more.
|
||||||
* Note that the number of bytes of instructions for adjusting r3 needs
|
* Note that the number of bytes of instructions for adjusting r3 needs
|
||||||
* to equal the amount of the adjustment, due to the trick of using
|
* to equal the amount of the adjustment, due to the trick of using
|
||||||
* .Lst_exc - r3_offset as the handler address.
|
* .Lst_exc - r3_offset as the handler address.
|
||||||
@ -400,10 +400,27 @@ stex; stb r0,0(r3)
|
|||||||
/* adjust by 4 */
|
/* adjust by 4 */
|
||||||
addi r3,r3,4
|
addi r3,r3,4
|
||||||
.Lst_exc:
|
.Lst_exc:
|
||||||
ld r6,-24(r1)
|
ld r6,-24(r1) /* original destination pointer */
|
||||||
ld r5,-8(r1)
|
ld r4,-16(r1) /* original source pointer */
|
||||||
add r6,r6,r5
|
ld r5,-8(r1) /* original number of bytes */
|
||||||
subf r3,r3,r6 /* #bytes not copied in r3 */
|
add r7,r6,r5
|
||||||
|
/*
|
||||||
|
* If the destination pointer isn't 8-byte aligned,
|
||||||
|
* we may have got the exception as a result of a
|
||||||
|
* store that overlapped a page boundary, so we may be
|
||||||
|
* able to copy a few more bytes.
|
||||||
|
*/
|
||||||
|
17: andi. r0,r3,7
|
||||||
|
beq 19f
|
||||||
|
subf r8,r6,r3 /* #bytes copied */
|
||||||
|
100: EX_TABLE(100b,19f)
|
||||||
|
lbzx r0,r8,r4
|
||||||
|
100: EX_TABLE(100b,19f)
|
||||||
|
stb r0,0(r3)
|
||||||
|
addi r3,r3,1
|
||||||
|
cmpld r3,r7
|
||||||
|
blt 17b
|
||||||
|
19: subf r3,r3,r7 /* #bytes not copied in r3 */
|
||||||
blr
|
blr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user