Messages in this thread | | | From | David Laight <> | Subject | RE: [PATCH] x86/uaccess: fix code generation in put_user() | Date | Sat, 24 Oct 2020 16:58:25 +0000 |
| |
From: David Laight > Sent: 23 October 2020 22:52 ... > Could do_put_user() do an initial check for 64 bit > then expand a different #define that contains the actual > code passing either "a" or "A" for the constriant. > > Apart from another level of indirection nothing is duplicated.
This code seems to compile to something sensible. It does need change the registers that get_user_n() must use - the normal return value is now in %ax (and %dx for 64bit values on 32bit systems, with the error in %cx. (I've not actually tested it.)
#define __inttype_max(x, _max) __typeof__( \ __typefits(x,char, \ __typefits(x,short, \ __typefits(x,int, \ __typefits(x,long,_max)))))
#define __inttype(x) __inttype_max(x, 0ULL)
#define get_user_1(x, ptr, type, constraint) \ ({ \ int __ret_gu; \ type __val_gu; \ asm volatile("call __get_user_%P4" \ : "=c" (__ret_gu), constraint (__val_gu), \ ASM_CALL_CONSTRAINT \ : "a" (ptr), "i" (sizeof(*(ptr)))); \ (x) = (__force __typeof__(*(ptr))) __val_gu; \ __builtin_expect(__ret_gu, 0); \ })
#define get_user(x, ptr) \ ({ \ __chk_user_ptr(ptr); \ might_fault(); \ (sizeof *(ptr) > sizeof(long)) \ ? get_user_1(x, ptr, long long, "=A") \ : get_user_1(x, ptr, __inttype_max(*(ptr),0ul), "=a"); \ })
The __inttype_max() is needed (I think) because clang will try (and fail) to generate the asm for 64bit values on 32bit systems. So the type needs limiting to 32bits. Always using 'long' works - but generates extra casts.
The "=A" constraint (%rax or %rdx) is never used on 64bit because the test is always false.
David
- Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
| |