diff options
| -rw-r--r-- | arch/alpha/Config.help | 6 | ||||
| -rw-r--r-- | arch/alpha/config.in | 4 | ||||
| -rw-r--r-- | arch/alpha/kernel/entry.S | 5 | ||||
| -rw-r--r-- | arch/alpha/kernel/osf_sys.c | 73 | ||||
| -rw-r--r-- | include/asm-alpha/a.out.h | 4 | ||||
| -rw-r--r-- | include/linux/personality.h | 1 |
6 files changed, 75 insertions, 18 deletions
diff --git a/arch/alpha/Config.help b/arch/alpha/Config.help index 922ce70ac5fd..e4ffe8437f20 100644 --- a/arch/alpha/Config.help +++ b/arch/alpha/Config.help @@ -438,6 +438,12 @@ CONFIG_BINFMT_AOUT because some crucial programs on your system might still be in A.OUT format. +OSF/1 v4 readv/writev compatibility +CONFIG_OSF4_COMPAT + Say Y if you are using OSF/1 binaries (like Netscape and Acrobat) + with v4 shared libraries freely available from Compaq. If you're + going to use shared libraries from Tru64 version 5.0 or later, say N. + CONFIG_BINFMT_EM86 Say Y here if you want to be able to execute Linux/Intel ELF binaries just like native Alpha binaries on your Alpha machine. For diff --git a/arch/alpha/config.in b/arch/alpha/config.in index e4cf0a6850d6..6b6d24bcafb4 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -265,6 +265,10 @@ if [ "$CONFIG_PROC_FS" != "n" ]; then fi tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT +if [ "$CONFIG_BINFMT_AOUT" != "n" ]; then + bool ' OSF/1 v4 readv/writev compatibility' CONFIG_OSF4_COMPAT +fi + tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86 diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 099430641f4a..144cafd1086a 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -851,8 +851,13 @@ sys_call_table: .quad osf_getrusage .quad sys_getsockopt .quad alpha_ni_syscall +#ifdef CONFIG_OSF4_COMPAT + .quad osf_readv /* 120 */ + .quad osf_writev +#else .quad sys_readv /* 120 */ .quad sys_writev +#endif .quad osf_settimeofday .quad sys_fchown .quad sys_fchmod diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 9dd48b15441c..0e66b34b1d80 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -33,6 +33,7 @@ #include <linux/file.h> #include <linux/types.h> #include <linux/ipc.h> +#include <linux/namei.h> #include <asm/fpu.h> #include <asm/io.h> @@ -956,6 +957,13 @@ static inline long put_it32(struct itimerval32 *o, struct itimerval *i) __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); } +static inline void +jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value) +{ + value->tv_usec = (jiffies % HZ) * (1000000L / HZ); + value->tv_sec = jiffies / HZ; +} + asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) { if (tv) { @@ -1163,32 +1171,24 @@ asmlinkage int osf_getrusage(int who, struct rusage32 *ru) memset(&r, 0, sizeof(r)); switch (who) { case RUSAGE_SELF: - r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime); - r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime); - r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime); - r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime); + jiffies_to_timeval32(current->utime, &r.ru_utime); + jiffies_to_timeval32(current->stime, &r.ru_stime); r.ru_minflt = current->min_flt; r.ru_majflt = current->maj_flt; r.ru_nswap = current->nswap; break; case RUSAGE_CHILDREN: - r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_cutime); - r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_cutime); - r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_cstime); - r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_cstime); + jiffies_to_timeval32(current->cutime, &r.ru_utime); + jiffies_to_timeval32(current->cstime, &r.ru_stime); r.ru_minflt = current->cmin_flt; r.ru_majflt = current->cmaj_flt; r.ru_nswap = current->cnswap; break; default: - r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime + - current->times.tms_cutime); - r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime + - current->times.tms_cutime); - r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime + - current->times.tms_cstime); - r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime + - current->times.tms_cstime); + jiffies_to_timeval32(current->utime + current->cutime, + &r.ru_utime); + jiffies_to_timeval32(current->stime + current->cstime, + &r.ru_stime); r.ru_minflt = current->min_flt + current->cmin_flt; r.ru_majflt = current->maj_flt + current->cmaj_flt; r.ru_nswap = current->nswap + current->cnswap; @@ -1390,3 +1390,44 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, return addr; } + +#ifdef CONFIG_OSF4_COMPAT +extern ssize_t sys_readv(unsigned long, const struct iovec *, unsigned long); +extern ssize_t sys_writev(unsigned long, const struct iovec *, unsigned long); + +/* Clear top 32 bits of iov_len in the user's buffer for + compatibility with old versions of OSF/1 where iov_len + was defined as int. */ +static int +osf_fix_iov_len(const struct iovec *iov, unsigned long count) +{ + unsigned long i; + + for (i = 0 ; i < count ; i++) { + int *iov_len_high = (int *)&iov[i].iov_len + 1; + + if (put_user(0, iov_len_high)) + return -EFAULT; + } + return 0; +} + +asmlinkage ssize_t +osf_readv(unsigned long fd, const struct iovec * vector, unsigned long count) +{ + if (unlikely(personality(current->personality) == PER_OSF4)) + if (osf_fix_iov_len(vector, count)) + return -EFAULT; + return sys_readv(fd, vector, count); +} + +asmlinkage ssize_t +osf_writev(unsigned long fd, const struct iovec * vector, unsigned long count) +{ + if (unlikely(personality(current->personality) == PER_OSF4)) + if (osf_fix_iov_len(vector, count)) + return -EFAULT; + return sys_writev(fd, vector, count); +} + +#endif diff --git a/include/asm-alpha/a.out.h b/include/asm-alpha/a.out.h index b0361104b290..709ea3e381c3 100644 --- a/include/asm-alpha/a.out.h +++ b/include/asm-alpha/a.out.h @@ -95,8 +95,8 @@ struct exec Worse, we have to notice the start address before swapping to use /sbin/loader, which of course is _not_ a TASO application. */ #define SET_AOUT_PERSONALITY(BFPM, EX) \ - set_personality (BFPM->sh_bang || EX.ah.entry < 0x100000000 \ - ? PER_LINUX_32BIT : PER_LINUX) + set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000 \ + ? ADDR_LIMIT_32BIT : 0) | PER_OSF4)) #define STACK_TOP \ (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL) diff --git a/include/linux/personality.h b/include/linux/personality.h index 230d39460364..192f073b0a5a 100644 --- a/include/linux/personality.h +++ b/include/linux/personality.h @@ -62,6 +62,7 @@ enum { PER_RISCOS = 0x000c, PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_OSF4 = 0x000f, /* OSF/1 v4 */ PER_MASK = 0x00ff, }; |
