On Tue, 28 Jun 2005 13:47:36 -0700 (PDT) "David S. Miller" <[EMAIL PROTECTED]> wrote: > > Why don't we do the following to resolve this issue? > Create a "is_compat_syscall()" macro, in compat syscall > trap entry, the bit is set, and it is cleared otherwise. > > It nops out to always evaluate to "0" on non-compat platforms.
How about the patch below which defines is_compat_syscall() for ppc64 (and all the non-compat-requiring archs)? (Yes, the ppc64 syscall entry really checks the thread flag.) The patch alos includes the fixes for the input layer mess. If this is acceptable, I will try to figure out what the macro should be for the other 64 bit architectures. -- Cheers, Stephen Rothwell [EMAIL PROTECTED] http://www.canb.auug.org.au/~sfr/ diff -ruN linus/drivers/input/evdev.c linus-compat_syscall.2/drivers/input/evdev.c --- linus/drivers/input/evdev.c 2005-06-28 10:05:26.000000000 +1000 +++ linus-compat_syscall.2/drivers/input/evdev.c 2005-06-29 16:00:58.000000000 +1000 @@ -154,16 +154,6 @@ __s32 value; }; -#ifdef CONFIG_X86_64 -# define COMPAT_TEST test_thread_flag(TIF_IA32) -#elif defined(CONFIG_IA64) -# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) -#elif defined(CONFIG_ARCH_S390) -# define COMPAT_TEST test_thread_flag(TIF_31BIT) -#else -# define COMPAT_TEST test_thread_flag(TIF_32BIT) -#endif - static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; @@ -179,6 +169,9 @@ return retval; } +#else +/* prototype to keep gcc quiet */ +ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos); #endif static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) @@ -189,10 +182,8 @@ if (!list->evdev->exist) return -ENODEV; -#ifdef CONFIG_COMPAT - if (COMPAT_TEST) + if (is_compat_syscall()) return evdev_write_compat(file, buffer, count, ppos); -#endif while (retval < count) { @@ -243,6 +234,9 @@ return retval; } +#else +/* prototype to keep gcc quiet */ +ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos); #endif static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) @@ -250,10 +244,8 @@ struct evdev_list *list = file->private_data; int retval; -#ifdef CONFIG_COMPAT - if (COMPAT_TEST) + if (is_compat_syscall()) return evdev_read_compat(file, buffer, count, ppos); -#endif if (count < sizeof(struct input_event)) return -EINVAL; @@ -484,34 +476,18 @@ #ifdef CONFIG_COMPAT -#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) -#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) -#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) +#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_COMPAT_LONG)+1) +#define OFF_COMPAT(x) ((x)%BITS_PER_COMPAT_LONG) #define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) -#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) +#define LONG_COMPAT(x) ((x)/BITS_PER_COMPAT_LONG) #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) -#ifdef __BIG_ENDIAN #define bit_to_user(bit, max) \ do { \ - int i; \ int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ - for (i = 0; i < len / sizeof(compat_long_t); i++) \ - if (copy_to_user((compat_long_t*) p + i, \ - (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ - sizeof(compat_long_t))) \ - return -EFAULT; \ - return len; \ + return compat_put_bitmap(p, (bit), len * 8) ? -EFAULT : len; \ } while (0) -#else -#define bit_to_user(bit, max) \ -do { \ - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ - return copy_to_user(p, (bit), len) ? -EFAULT : len; \ -} while (0) -#endif static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { @@ -631,6 +607,8 @@ } return -EINVAL; } +#else +#define evdev_ioctl_compat NULL #endif static struct file_operations evdev_fops = { @@ -641,9 +619,7 @@ .open = evdev_open, .release = evdev_release, .unlocked_ioctl = evdev_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = evdev_ioctl_compat, -#endif .fasync = evdev_fasync, .flush = evdev_flush }; diff -ruN linus/include/asm-ppc64/compat.h linus-compat_syscall.2/include/asm-ppc64/compat.h --- linus/include/asm-ppc64/compat.h 2005-06-27 16:08:08.000000000 +1000 +++ linus-compat_syscall.2/include/asm-ppc64/compat.h 2005-06-29 15:15:27.000000000 +1000 @@ -200,4 +200,6 @@ compat_ulong_t __unused6; }; +#define is_compat_syscall() test_tsk_thread_flag(current, TIF_32BIT) + #endif /* _ASM_PPC64_COMPAT_H */ diff -ruN linus/include/linux/compat.h linus-compat_syscall.2/include/linux/compat.h --- linus/include/linux/compat.h 2005-06-27 16:08:11.000000000 +1000 +++ linus-compat_syscall.2/include/linux/compat.h 2005-06-29 16:38:46.000000000 +1000 @@ -158,5 +158,15 @@ int get_compat_sigevent(struct sigevent *event, const struct compat_sigevent __user *u_event); +#else /* CONFIG_COMPAT */ + +/* + * The is_compat_syscall() macro returns true if the current syscall + * was done through the comaptibility ABI. We define it to be zero on + * platforms without a compatibility ABI so that the compiler can remove + * compatibility code from those platforms. + */ +#define is_compat_syscall() 0 + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */
pgph5qImraiv1.pgp
Description: PGP signature
