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.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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
|
|
|
|
2008-07-07 22:28:54 +08:00
|
|
|
if (!arch_validate_prot(prot))
|
|
|
|
goto out;
|
|
|
|
|
2005-10-17 18:10:13 +08:00
|
|
|
if (shift) {
|
|
|
|
if (off & ((1 << shift) - 1))
|
|
|
|
goto out;
|
|
|
|
off >>= shift;
|
|
|
|
}
|
|
|
|
|
2009-12-01 06:37:04 +08:00
|
|
|
ret = sys_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
|
|
|
|
ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
|
|
|
|
{
|
|
|
|
if ( (unsigned long)n >= 4096 )
|
|
|
|
{
|
|
|
|
unsigned long __user *buffer = (unsigned long __user *)n;
|
|
|
|
if (!access_ok(VERIFY_READ, buffer, 5*sizeof(unsigned long))
|
|
|
|
|| __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)))
|
|
|
|
|| __get_user(tvp, ((struct timeval __user * __user *)(buffer+4))))
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low,
|
|
|
|
(u64)len_high << 32 | len_low, advice);
|
|
|
|
}
|
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
|
|
|
|
|
|
|
long sys_switch_endian(void)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|