On Fri, Nov 09, 2012 at 09:17:33PM +0000, Rob Clark wrote: > From: Rob Clark <rob@xxxxxx> > > A new atomic modeset/pageflip ioctl being developed in DRM requires > get_user() to work for 64bit types (in addition to just put_user()). > > Signed-off-by: Rob Clark <rob@xxxxxx> > --- > arch/arm/include/asm/uaccess.h | 25 ++++++++++++++++++++----- > arch/arm/lib/getuser.S | 17 ++++++++++++++++- > 2 files changed, 36 insertions(+), 6 deletions(-) > > diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h > index 7e1f760..2e3fdb2 100644 > --- a/arch/arm/include/asm/uaccess.h > +++ b/arch/arm/include/asm/uaccess.h > @@ -100,6 +100,7 @@ static inline void set_fs(mm_segment_t fs) > extern int __get_user_1(void *); > extern int __get_user_2(void *); > extern int __get_user_4(void *); > +extern int __get_user_8(void *); > > #define __GUP_CLOBBER_1 "lr", "cc" > #ifdef CONFIG_CPU_USE_DOMAINS > @@ -108,6 +109,7 @@ extern int __get_user_4(void *); > #define __GUP_CLOBBER_2 "lr", "cc" > #endif > #define __GUP_CLOBBER_4 "lr", "cc" > +#define __GUP_CLOBBER_8 "lr", "cc" > > #define __get_user_x(__r2,__p,__e,__l,__s) \ > __asm__ __volatile__ ( \ > @@ -122,22 +124,35 @@ extern int __get_user_4(void *); > ({ \ > unsigned long __limit = current_thread_info()->addr_limit - 1; \ > register const typeof(*(p)) __user *__p asm("r0") = (p);\ > - register unsigned long __r2 asm("r2"); \ > register unsigned long __l asm("r1") = __limit; \ > register int __e asm("r0"); \ > switch (sizeof(*(__p))) { \ > - case 1: \ > + case 1: { \ > + register unsigned long __r2 asm("r2"); \ > __get_user_x(__r2, __p, __e, __l, 1); \ > + x = (typeof(*(p))) __r2; \ > break; \ > - case 2: \ > + } \ > + case 2: { \ > + register unsigned long __r2 asm("r2"); \ > __get_user_x(__r2, __p, __e, __l, 2); \ > + x = (typeof(*(p))) __r2; \ > break; \ > - case 4: \ > + } \ > + case 4: { \ > + register unsigned long __r2 asm("r2"); \ > __get_user_x(__r2, __p, __e, __l, 4); \ > + x = (typeof(*(p))) __r2; \ > + break; \ > + } \ > + case 8: { \ > + register unsigned long long __r2 asm("r2"); \ Does this matter? For EABI, we'll pass in (r2, r3) and it's all handcrafted asm, so the compiler shouldn't care much. For OABI, I think you may have to do some more work to get the two words where you want them. > + __get_user_x(__r2, __p, __e, __l, 8); \ > + x = (typeof(*(p))) __r2; \ > break; \ > + } \ > default: __e = __get_user_bad(); break; \ > } \ > - x = (typeof(*(p))) __r2; \ > __e; \ > }) > > diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S > index 9b06bb4..d05285c 100644 > --- a/arch/arm/lib/getuser.S > +++ b/arch/arm/lib/getuser.S > @@ -18,7 +18,7 @@ > * Inputs: r0 contains the address > * r1 contains the address limit, which must be preserved > * Outputs: r0 is the error code > - * r2 contains the zero-extended value > + * r2, r3 contains the zero-extended value > * lr corrupted > * > * No other registers must be altered. (see <asm/uaccess.h> > @@ -66,6 +66,19 @@ ENTRY(__get_user_4) > mov pc, lr > ENDPROC(__get_user_4) > > +ENTRY(__get_user_8) > + check_uaccess r0, 4, r1, r2, __get_user_bad Shouldn't you be passing 8 here, so that we validate the correct range? > +#ifdef CONFIG_THUMB2_KERNEL > +5: TUSER(ldr) r2, [r0] > +6: TUSER(ldr) r3, [r0, #4] > +#else > +5: TUSER(ldr) r2, [r0], #4 > +6: TUSER(ldr) r3, [r0] > +#endif This doesn't work for EABI big-endian systems. Will -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html