Commit 4b9d2a73 authored by Helge Deller's avatar Helge Deller

parisc: Switch user access functions to signal errors in r29 instead of r8

Use register r29 instead of register r8 to signal faults when accessing
user memory. In case of faults, the fixup routine will store -EFAULT in
this register.

This change saves up to 752 bytes on a 32bit kernel, partly because the
compiler doesn't need to save and restore the old r8 value on the stack.

bloat-o-meter results for usage with r29 register:
add/remove: 0/0 grow/shrink: 23/86 up/down: 228/-980 (-752)

bloat-o-meter results for usage with r28 register:
add/remove: 0/0 grow/shrink: 28/83 up/down: 296/-956 (-660)
Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent 9e9d4b46
...@@ -53,15 +53,18 @@ struct exception_table_entry { ...@@ -53,15 +53,18 @@ struct exception_table_entry {
/* /*
* ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry
* (with lowest bit set) for which the fault handler in fixup_exception() will * (with lowest bit set) for which the fault handler in fixup_exception() will
* load -EFAULT into %r8 for a read or write fault, and zeroes the target * load -EFAULT into %r29 for a read or write fault, and zeroes the target
* register in case of a read fault in get_user(). * register in case of a read fault in get_user().
*/ */
#define ASM_EXCEPTIONTABLE_REG 29
#define ASM_EXCEPTIONTABLE_VAR(__variable) \
register long __variable __asm__ ("r29") = 0
#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\ #define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\
ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1) ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1)
#define __get_user_internal(sr, val, ptr) \ #define __get_user_internal(sr, val, ptr) \
({ \ ({ \
register long __gu_err __asm__ ("r8") = 0; \ ASM_EXCEPTIONTABLE_VAR(__gu_err); \
\ \
switch (sizeof(*(ptr))) { \ switch (sizeof(*(ptr))) { \
case 1: __get_user_asm(sr, val, "ldb", ptr); break; \ case 1: __get_user_asm(sr, val, "ldb", ptr); break; \
...@@ -131,7 +134,7 @@ struct exception_table_entry { ...@@ -131,7 +134,7 @@ struct exception_table_entry {
#define __put_user_internal(sr, x, ptr) \ #define __put_user_internal(sr, x, ptr) \
({ \ ({ \
register long __pu_err __asm__ ("r8") = 0; \ ASM_EXCEPTIONTABLE_VAR(__pu_err); \
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
\ \
switch (sizeof(*(ptr))) { \ switch (sizeof(*(ptr))) { \
...@@ -168,7 +171,8 @@ struct exception_table_entry { ...@@ -168,7 +171,8 @@ struct exception_table_entry {
* gcc knows about, so there are no aliasing issues. These macros must * gcc knows about, so there are no aliasing issues. These macros must
* also be aware that fixups are executed in the context of the fault, * also be aware that fixups are executed in the context of the fault,
* and any registers used there must be listed as clobbers. * and any registers used there must be listed as clobbers.
* r8 is already listed as err. * The register holding the possible EFAULT error (ASM_EXCEPTIONTABLE_REG)
* is already listed as input and output register.
*/ */
#define __put_user_asm(sr, stx, x, ptr) \ #define __put_user_asm(sr, stx, x, ptr) \
......
...@@ -148,11 +148,11 @@ int fixup_exception(struct pt_regs *regs) ...@@ -148,11 +148,11 @@ int fixup_exception(struct pt_regs *regs)
* Fix up get_user() and put_user(). * Fix up get_user() and put_user().
* ASM_EXCEPTIONTABLE_ENTRY_EFAULT() sets the least-significant * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() sets the least-significant
* bit in the relative address of the fixup routine to indicate * bit in the relative address of the fixup routine to indicate
* that %r8 should be loaded with -EFAULT to report a userspace * that gr[ASM_EXCEPTIONTABLE_REG] should be loaded with
* access error. * -EFAULT to report a userspace access error.
*/ */
if (fix->fixup & 1) { if (fix->fixup & 1) {
regs->gr[8] = -EFAULT; regs->gr[ASM_EXCEPTIONTABLE_REG] = -EFAULT;
/* zero target register for get_user() */ /* zero target register for get_user() */
if (parisc_acctyp(0, regs->iir) == VM_READ) { if (parisc_acctyp(0, regs->iir) == VM_READ) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment