2019-05-27 14:55:01 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2005-10-17 18:10:13 +08:00
|
|
|
* Implementation of various system calls for Linux/PowerPC
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
|
|
|
*
|
|
|
|
* Derived from "arch/i386/kernel/sys_i386.c"
|
|
|
|
* Adapted from the i386 version by Gary Thomas
|
|
|
|
* Modified by Cort Dougan (cort@cs.nmt.edu)
|
|
|
|
* and Paul Mackerras (paulus@cs.anu.edu.au).
|
|
|
|
*
|
|
|
|
* This file contains various random system calls that
|
|
|
|
* have a non-standard calling sequence on the Linux/PPC
|
|
|
|
* platform.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/syscalls.h>
|
|
|
|
#include <linux/mm.h>
|
2007-07-30 06:36:13 +08:00
|
|
|
#include <linux/fs.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/smp.h>
|
|
|
|
#include <linux/sem.h>
|
|
|
|
#include <linux/msg.h>
|
|
|
|
#include <linux/shm.h>
|
|
|
|
#include <linux/stat.h>
|
|
|
|
#include <linux/mman.h>
|
|
|
|
#include <linux/sys.h>
|
|
|
|
#include <linux/ipc.h>
|
|
|
|
#include <linux/utsname.h>
|
|
|
|
#include <linux/file.h>
|
|
|
|
#include <linux/personality.h>
|
|
|
|
|
2016-12-25 03:46:01 +08:00
|
|
|
#include <linux/uaccess.h>
|
2006-03-23 07:00:08 +08:00
|
|
|
#include <asm/syscalls.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/time.h>
|
|
|
|
#include <asm/unistd.h>
|
2016-09-06 13:32:43 +08:00
|
|
|
#include <asm/asm-prototypes.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
powerpc/tracing: Allow tracing of mmap syscalls
Currently sys_mmap() and sys_mmap2() (32-bit only), are not visible to the
syscall tracing machinery. This means users are not able to see the execution of
mmap() syscalls using the syscall tracer.
Fix that by using SYSCALL_DEFINE6 for sys_mmap() and sys_mmap2() so that the
meta-data associated with these syscalls is visible to the syscall tracer.
A side-effect of this change is that the return type has changed from unsigned
long to long. However this should have no effect, the only code in the kernel
which uses the result of these syscalls is in the syscall return path, which is
written in asm and treats the result as unsigned regardless.
Example output:
cat-3399 [001] .... 196.542410: sys_mmap(addr: 7fff922a0000, len: 20000, prot: 3, flags: 812, fd: 3, offset: 1b0000)
cat-3399 [001] .... 196.542443: sys_mmap -> 0x7fff922a0000
cat-3399 [001] .... 196.542668: sys_munmap(addr: 7fff922c0000, len: 6d2c)
cat-3399 [001] .... 196.542677: sys_munmap -> 0x0
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
[mpe: Massage change log, add detail on return type change]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2017-04-12 14:35:19 +08:00
|
|
|
static inline long do_mmap2(unsigned long addr, size_t len,
|
2005-10-17 18:10:13 +08:00
|
|
|
unsigned long prot, unsigned long flags,
|
|
|
|
unsigned long fd, unsigned long off, int shift)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
powerpc/tracing: Allow tracing of mmap syscalls
Currently sys_mmap() and sys_mmap2() (32-bit only), are not visible to the
syscall tracing machinery. This means users are not able to see the execution of
mmap() syscalls using the syscall tracer.
Fix that by using SYSCALL_DEFINE6 for sys_mmap() and sys_mmap2() so that the
meta-data associated with these syscalls is visible to the syscall tracer.
A side-effect of this change is that the return type has changed from unsigned
long to long. However this should have no effect, the only code in the kernel
which uses the result of these syscalls is in the syscall return path, which is
written in asm and treats the result as unsigned regardless.
Example output:
cat-3399 [001] .... 196.542410: sys_mmap(addr: 7fff922a0000, len: 20000, prot: 3, flags: 812, fd: 3, offset: 1b0000)
cat-3399 [001] .... 196.542443: sys_mmap -> 0x7fff922a0000
cat-3399 [001] .... 196.542668: sys_munmap(addr: 7fff922c0000, len: 6d2c)
cat-3399 [001] .... 196.542677: sys_munmap -> 0x0
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
[mpe: Massage change log, add detail on return type change]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2017-04-12 14:35:19 +08:00
|
|
|
long ret = -EINVAL;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2018-02-22 01:15:49 +08:00
|
|
|
if (!arch_validate_prot(prot, addr))
|
2008-07-07 22:28:54 +08:00
|
|
|
goto out;
|
|
|
|
|
2005-10-17 18:10:13 +08:00
|
|
|
if (shift) {
|
|
|
|
if (off & ((1 << shift) - 1))
|
|
|
|
goto out;
|
|
|
|
off >>= shift;
|
|
|
|
}
|
|
|
|
|
2018-03-11 18:34:46 +08:00
|
|
|
ret = ksys_mmap_pgoff(addr, len, prot, flags, fd, off);
|
2005-04-17 06:20:36 +08:00
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
powerpc/tracing: Allow tracing of mmap syscalls
Currently sys_mmap() and sys_mmap2() (32-bit only), are not visible to the
syscall tracing machinery. This means users are not able to see the execution of
mmap() syscalls using the syscall tracer.
Fix that by using SYSCALL_DEFINE6 for sys_mmap() and sys_mmap2() so that the
meta-data associated with these syscalls is visible to the syscall tracer.
A side-effect of this change is that the return type has changed from unsigned
long to long. However this should have no effect, the only code in the kernel
which uses the result of these syscalls is in the syscall return path, which is
written in asm and treats the result as unsigned regardless.
Example output:
cat-3399 [001] .... 196.542410: sys_mmap(addr: 7fff922a0000, len: 20000, prot: 3, flags: 812, fd: 3, offset: 1b0000)
cat-3399 [001] .... 196.542443: sys_mmap -> 0x7fff922a0000
cat-3399 [001] .... 196.542668: sys_munmap(addr: 7fff922c0000, len: 6d2c)
cat-3399 [001] .... 196.542677: sys_munmap -> 0x0
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
[mpe: Massage change log, add detail on return type change]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2017-04-12 14:35:19 +08:00
|
|
|
SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len,
|
|
|
|
unsigned long, prot, unsigned long, flags,
|
|
|
|
unsigned long, fd, unsigned long, pgoff)
|
2005-10-17 18:10:13 +08:00
|
|
|
{
|
|
|
|
return do_mmap2(addr, len, prot, flags, fd, pgoff, PAGE_SHIFT-12);
|
|
|
|
}
|
|
|
|
|
powerpc/tracing: Allow tracing of mmap syscalls
Currently sys_mmap() and sys_mmap2() (32-bit only), are not visible to the
syscall tracing machinery. This means users are not able to see the execution of
mmap() syscalls using the syscall tracer.
Fix that by using SYSCALL_DEFINE6 for sys_mmap() and sys_mmap2() so that the
meta-data associated with these syscalls is visible to the syscall tracer.
A side-effect of this change is that the return type has changed from unsigned
long to long. However this should have no effect, the only code in the kernel
which uses the result of these syscalls is in the syscall return path, which is
written in asm and treats the result as unsigned regardless.
Example output:
cat-3399 [001] .... 196.542410: sys_mmap(addr: 7fff922a0000, len: 20000, prot: 3, flags: 812, fd: 3, offset: 1b0000)
cat-3399 [001] .... 196.542443: sys_mmap -> 0x7fff922a0000
cat-3399 [001] .... 196.542668: sys_munmap(addr: 7fff922c0000, len: 6d2c)
cat-3399 [001] .... 196.542677: sys_munmap -> 0x0
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
[mpe: Massage change log, add detail on return type change]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2017-04-12 14:35:19 +08:00
|
|
|
SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len,
|
|
|
|
unsigned long, prot, unsigned long, flags,
|
|
|
|
unsigned long, fd, off_t, offset)
|
2005-10-17 18:10:13 +08:00
|
|
|
{
|
|
|
|
return do_mmap2(addr, len, prot, flags, fd, offset, PAGE_SHIFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_PPC32
|
|
|
|
/*
|
|
|
|
* Due to some executables calling the wrong select we sometimes
|
|
|
|
* get wrong args. This determines how the args are being passed
|
|
|
|
* (a single ptr to them all args passed) then calls
|
|
|
|
* sys_select() with the appropriate args. -- Cort
|
|
|
|
*/
|
|
|
|
int
|
2019-10-26 04:56:17 +08:00
|
|
|
ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct __kernel_old_timeval __user *tvp)
|
2005-10-17 18:10:13 +08:00
|
|
|
{
|
|
|
|
if ( (unsigned long)n >= 4096 )
|
|
|
|
{
|
|
|
|
unsigned long __user *buffer = (unsigned long __user *)n;
|
Remove 'type' argument from access_ok() function
Nobody has actually used the type (VERIFY_READ vs VERIFY_WRITE) argument
of the user address range verification function since we got rid of the
old racy i386-only code to walk page tables by hand.
It existed because the original 80386 would not honor the write protect
bit when in kernel mode, so you had to do COW by hand before doing any
user access. But we haven't supported that in a long time, and these
days the 'type' argument is a purely historical artifact.
A discussion about extending 'user_access_begin()' to do the range
checking resulted this patch, because there is no way we're going to
move the old VERIFY_xyz interface to that model. And it's best done at
the end of the merge window when I've done most of my merges, so let's
just get this done once and for all.
This patch was mostly done with a sed-script, with manual fix-ups for
the cases that weren't of the trivial 'access_ok(VERIFY_xyz' form.
There were a couple of notable cases:
- csky still had the old "verify_area()" name as an alias.
- the iter_iov code had magical hardcoded knowledge of the actual
values of VERIFY_{READ,WRITE} (not that they mattered, since nothing
really used it)
- microblaze used the type argument for a debug printout
but other than those oddities this should be a total no-op patch.
I tried to fix up all architectures, did fairly extensive grepping for
access_ok() uses, and the changes are trivial, but I may have missed
something. Any missed conversion should be trivially fixable, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-01-04 10:57:57 +08:00
|
|
|
if (!access_ok(buffer, 5*sizeof(unsigned long))
|
2005-10-17 18:10:13 +08:00
|
|
|
|| __get_user(n, buffer)
|
|
|
|
|| __get_user(inp, ((fd_set __user * __user *)(buffer+1)))
|
|
|
|
|| __get_user(outp, ((fd_set __user * __user *)(buffer+2)))
|
|
|
|
|| __get_user(exp, ((fd_set __user * __user *)(buffer+3)))
|
2019-10-26 04:56:17 +08:00
|
|
|
|| __get_user(tvp, ((struct __kernel_old_timeval __user * __user *)(buffer+4))))
|
2005-10-17 18:10:13 +08:00
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
return sys_select(n, inp, outp, exp, tvp);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_PPC64
|
2005-06-08 19:59:15 +08:00
|
|
|
long ppc64_personality(unsigned long personality)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-06-08 19:59:15 +08:00
|
|
|
long ret;
|
|
|
|
|
|
|
|
if (personality(current->personality) == PER_LINUX32
|
2012-08-13 11:18:28 +08:00
|
|
|
&& personality(personality) == PER_LINUX)
|
|
|
|
personality = (personality & ~PER_MASK) | PER_LINUX32;
|
2005-06-08 19:59:15 +08:00
|
|
|
ret = sys_personality(personality);
|
2012-08-13 11:18:28 +08:00
|
|
|
if (personality(ret) == PER_LINUX32)
|
|
|
|
ret = (ret & ~PER_MASK) | PER_LINUX;
|
2005-06-08 19:59:15 +08:00
|
|
|
return ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2005-10-17 18:10:13 +08:00
|
|
|
#endif
|
|
|
|
|
2005-10-18 12:19:41 +08:00
|
|
|
long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
|
|
|
|
u32 len_high, u32 len_low)
|
|
|
|
{
|
2018-03-11 18:34:45 +08:00
|
|
|
return ksys_fadvise64_64(fd, (u64)offset_high << 32 | offset_low,
|
|
|
|
(u64)len_high << 32 | len_low, advice);
|
2005-10-18 12:19:41 +08:00
|
|
|
}
|
powerpc: Add a proper syscall for switching endianness
We currently have a "special" syscall for switching endianness. This is
syscall number 0x1ebe, which is handled explicitly in the 64-bit syscall
exception entry.
That has a few problems, firstly the syscall number is outside of the
usual range, which confuses various tools. For example strace doesn't
recognise the syscall at all.
Secondly it's handled explicitly as a special case in the syscall
exception entry, which is complicated enough without it.
As a first step toward removing the special syscall, we need to add a
regular syscall that implements the same functionality.
The logic is simple, it simply toggles the MSR_LE bit in the userspace
MSR. This is the same as the special syscall, with the caveat that the
special syscall clobbers fewer registers.
This version clobbers r9-r12, XER, CTR, and CR0-1,5-7.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2015-03-28 18:35:16 +08:00
|
|
|
|
2019-01-15 14:37:36 +08:00
|
|
|
SYSCALL_DEFINE0(switch_endian)
|
powerpc: Add a proper syscall for switching endianness
We currently have a "special" syscall for switching endianness. This is
syscall number 0x1ebe, which is handled explicitly in the 64-bit syscall
exception entry.
That has a few problems, firstly the syscall number is outside of the
usual range, which confuses various tools. For example strace doesn't
recognise the syscall at all.
Secondly it's handled explicitly as a special case in the syscall
exception entry, which is complicated enough without it.
As a first step toward removing the special syscall, we need to add a
regular syscall that implements the same functionality.
The logic is simple, it simply toggles the MSR_LE bit in the userspace
MSR. This is the same as the special syscall, with the caveat that the
special syscall clobbers fewer registers.
This version clobbers r9-r12, XER, CTR, and CR0-1,5-7.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2015-03-28 18:35:16 +08:00
|
|
|
{
|
|
|
|
struct thread_info *ti;
|
|
|
|
|
|
|
|
current->thread.regs->msr ^= MSR_LE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set TIF_RESTOREALL so that r3 isn't clobbered on return to
|
|
|
|
* userspace. That also has the effect of restoring the non-volatile
|
|
|
|
* GPRs, so we saved them on the way in here.
|
|
|
|
*/
|
|
|
|
ti = current_thread_info();
|
|
|
|
ti->flags |= _TIF_RESTOREALL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|