PER_LINUX32 fixes reworked
Paul Mackerras
paulus at samba.org
Thu May 19 16:10:42 EST 2005
I have reworked Juergen Kreileder's patch to fix some PER_LINUX32
things a bit. I took the opportunity to move the ppc32-specific uname
functions to sys_ppc32.c, and move the functions that are used for
both 32-bit and 64-bit processes from sys_ppc32.c to syscalls.c.
We still have one difference from x86_64 in that once a process has
set its personality to PER_LINUX32, if it asks what its personality is
it will be told PER_LINUX, and if it tries to set the personality to
PER_LINUX it will remain as PER_LINUX32. We do that for both 32-bit
and 64-bit processes, whereas x86_64 does it only for 32-bit processes
(sparc64 does it for both 32-bit and 64-bit).
Note that the only difference PER_LINUX32 makes is to change the value
returned in the utsname machine field by the uname syscalls from
"ppc64" to "ppc", and thus uname -m will print ppc rather than ppc64.
I'd like to get rid of the "fakeppc" kernel command-line option
someday too. Does anyone actually still use it?
Comments? If no-one has any problems with this patch I'll send it
upstream.
Paul.
diff -urN linux-2.6/arch/ppc64/kernel/misc.S g5-ppc64/arch/ppc64/kernel/misc.S
--- linux-2.6/arch/ppc64/kernel/misc.S 2005-05-06 15:49:24.000000000 +1000
+++ g5-ppc64/arch/ppc64/kernel/misc.S 2005-05-18 16:02:37.000000000 +1000
@@ -792,7 +792,7 @@
.llong .compat_sys_newstat
.llong .compat_sys_newlstat
.llong .compat_sys_newfstat
- .llong .sys_uname
+ .llong .sys32_uname
.llong .sys_ni_syscall /* 110 old iopl syscall */
.llong .sys_vhangup
.llong .sys_ni_syscall /* old idle syscall */
diff -urN linux-2.6/arch/ppc64/kernel/sys_ppc32.c g5-ppc64/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.6/arch/ppc64/kernel/sys_ppc32.c 2005-04-26 15:37:55
+++ g5-ppc64/arch/ppc64/kernel/sys_ppc32.c 2005-05-19 15:30:59
@@ -788,34 +788,9 @@
}
return -EOPNOTSUPP;
-}
-
-
-asmlinkage int ppc64_newuname(struct new_utsname __user * name)
-{
- int errno = sys_newuname(name);
-
- if (current->personality == PER_LINUX32 && !errno) {
- if(copy_to_user(name->machine, "ppc\0\0", 8)) {
- errno = -EFAULT;
- }
- }
- return errno;
-}
-
-asmlinkage int ppc64_personality(unsigned long personality)
-{
- int ret;
- if (current->personality == PER_LINUX32 && personality == PER_LINUX)
- personality = PER_LINUX32;
- ret = sys_personality(personality);
- if (ret == PER_LINUX32)
- ret = PER_LINUX;
- return ret;
}
-
/* Note: it is necessary to treat mode as an unsigned int,
* with the corresponding cast to a signed int to insure that the
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1158,26 +1133,47 @@
}
#endif
+asmlinkage int sys32_uname(struct old_utsname __user * name)
+{
+ int err = 0;
+
+ down_read(&uts_sem);
+ if (copy_to_user(name, &system_utsname, sizeof(*name)))
+ err = -EFAULT;
+ up_read(&uts_sem);
+ if (!err && personality(current->personality) == PER_LINUX32) {
+ /* change "ppc64" to "ppc" */
+ if (__put_user(0, name->machine + 3)
+ || __put_user(0, name->machine + 4))
+ err = -EFAULT;
+ }
+ return err;
+}
+
asmlinkage int sys32_olduname(struct oldold_utsname __user * name)
{
int error;
-
- if (!name)
- return -EFAULT;
+
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
return -EFAULT;
down_read(&uts_sem);
error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
- error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
- error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
- error -= __put_user(0,name->release+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
- error -= __put_user(0,name->version+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
- error = __put_user(0,name->machine+__OLD_UTS_LEN);
+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+ error |= __put_user(0,name->release+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+ error |= __put_user(0,name->version+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+ error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+ if (personality(current->personality) == PER_LINUX32) {
+ /* change "ppc64" to "ppc" */
+ error |= __put_user(0, name->machine + 3);
+ error |= __put_user(0, name->machine + 4);
+ }
+
up_read(&uts_sem);
error = error ? -EFAULT : 0;
diff -urN linux-2.6/arch/ppc64/kernel/syscalls.c g5-ppc64/arch/ppc64/kernel/syscalls.c
--- linux-2.6/arch/ppc64/kernel/syscalls.c 2005-04-26 15:37:55.000000000 +1000
+++ g5-ppc64/arch/ppc64/kernel/syscalls.c 2005-05-18 17:09:02.000000000 +1000
@@ -208,15 +208,33 @@
}
__setup("fakeppc", set_fakeppc);
-asmlinkage int sys_uname(struct old_utsname __user * name)
+long ppc64_personality(unsigned long personality)
{
- int err = -EFAULT;
-
+ long ret;
+
+ if (personality(current->personality) == PER_LINUX32
+ && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
+}
+
+long ppc64_newuname(struct new_utsname __user * name)
+{
+ int err = 0;
+
down_read(&uts_sem);
- if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
- err = 0;
+ if (copy_to_user(name, &system_utsname, sizeof(*name)))
+ err = -EFAULT;
up_read(&uts_sem);
-
+ if (!err && personality(current->personality) == PER_LINUX32) {
+ /* change ppc64 to ppc */
+ if (__put_user(0, name->machine + 3)
+ || __put_user(0, name->machine + 4))
+ err = -EFAULT;
+ }
return err;
}
diff -urN linux-2.6/include/asm-ppc64/elf.h g5-ppc64/include/asm-ppc64/elf.h
--- linux-2.6/include/asm-ppc64/elf.h 2005-05-02 08:29:41.000000000 +1000
+++ g5-ppc64/include/asm-ppc64/elf.h 2005-05-18 16:16:34.000000000 +1000
@@ -221,9 +221,7 @@
set_thread_flag(TIF_ABI_PENDING); \
else \
clear_thread_flag(TIF_ABI_PENDING); \
- if (ibcs2) \
- set_personality(PER_SVR4); \
- else if (current->personality != PER_LINUX32) \
+ if (personality(current->personality) != PER_LINUX32) \
set_personality(PER_LINUX); \
} while (0)
More information about the Linuxppc64-dev
mailing list