Commit 3dd681d9 authored by Will Deacon's avatar Will Deacon Committed by Catalin Marinas

arm64: 32-bit (compat) applications support

This patch adds support for 32-bit applications. The vectors page is a
binary blob mapped into the application user space at 0xffff0000 (the
AArch64 toolchain does not support compilation of AArch32 code). Full
compatibility with ARMv7 user space is supported. The use of deprecated
ARMv7 functionality (SWP, CP15 barriers) has been disabled by default on
AArch64 kernels and unaligned LDM/STM is not supported.

Please note that only the ARM 32-bit EABI is supported, so no OABI
compatibility.
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarTony Lindgren <tony@atomide.com>
Acked-by: default avatarNicolas Pitre <nico@linaro.org>
Acked-by: default avatarOlof Johansson <olof@lixom.net>
Acked-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
parent 0aea86a2
/*
* Copyright (C) 2012 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_COMPAT_H
#define __ASM_COMPAT_H
#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
/*
* Architecture specific compatibility types
*/
#include <linux/types.h>
#include <linux/sched.h>
#define COMPAT_USER_HZ 100
#define COMPAT_UTS_MACHINE "armv8l\0\0"
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
typedef u32 __compat_uid_t;
typedef u32 __compat_gid_t;
typedef u32 __compat_uid32_t;
typedef u32 __compat_gid32_t;
typedef u32 compat_mode_t;
typedef u32 compat_ino_t;
typedef u32 compat_dev_t;
typedef s32 compat_off_t;
typedef s64 compat_loff_t;
typedef s16 compat_nlink_t;
typedef u16 compat_ipc_pid_t;
typedef s32 compat_daddr_t;
typedef u32 compat_caddr_t;
typedef __kernel_fsid_t compat_fsid_t;
typedef s32 compat_key_t;
typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
typedef s64 compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
typedef u64 compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
s32 tv_nsec;
};
struct compat_timeval {
compat_time_t tv_sec;
s32 tv_usec;
};
struct compat_stat {
compat_dev_t st_dev;
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
__compat_uid32_t st_uid;
__compat_gid32_t st_gid;
compat_dev_t st_rdev;
compat_off_t st_size;
compat_off_t st_blksize;
compat_off_t st_blocks;
compat_time_t st_atime;
u32 st_atime_nsec;
compat_time_t st_mtime;
u32 st_mtime_nsec;
compat_time_t st_ctime;
u32 st_ctime_nsec;
u32 __unused4[2];
};
struct compat_flock {
short l_type;
short l_whence;
compat_off_t l_start;
compat_off_t l_len;
compat_pid_t l_pid;
};
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
struct compat_flock64 {
short l_type;
short l_whence;
compat_loff_t l_start;
compat_loff_t l_len;
compat_pid_t l_pid;
};
struct compat_statfs {
int f_type;
int f_bsize;
int f_blocks;
int f_bfree;
int f_bavail;
int f_files;
int f_ffree;
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
int f_flags;
int f_spare[4];
};
#define COMPAT_RLIM_INFINITY 0xffffffff
typedef u32 compat_old_sigset_t;
#define _COMPAT_NSIG 64
#define _COMPAT_NSIG_BPW 32
typedef u32 compat_sigset_word;
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
/*
* A pointer passed in from user mode. This should not
* be used for syscall parameters, just declare them
* as pointers because the syscall entry code will have
* appropriately converted them already.
*/
typedef u32 compat_uptr_t;
static inline void __user *compat_ptr(compat_uptr_t uptr)
{
return (void __user *)(unsigned long)uptr;
}
static inline compat_uptr_t ptr_to_compat(void __user *uptr)
{
return (u32)(unsigned long)uptr;
}
static inline void __user *arch_compat_alloc_user_space(long len)
{
struct pt_regs *regs = task_pt_regs(current);
return (void __user *)regs->compat_sp - len;
}
struct compat_ipc64_perm {
compat_key_t key;
__compat_uid32_t uid;
__compat_gid32_t gid;
__compat_uid32_t cuid;
__compat_gid32_t cgid;
unsigned short mode;
unsigned short __pad1;
unsigned short seq;
unsigned short __pad2;
compat_ulong_t unused1;
compat_ulong_t unused2;
};
struct compat_semid64_ds {
struct compat_ipc64_perm sem_perm;
compat_time_t sem_otime;
compat_ulong_t __unused1;
compat_time_t sem_ctime;
compat_ulong_t __unused2;
compat_ulong_t sem_nsems;
compat_ulong_t __unused3;
compat_ulong_t __unused4;
};
struct compat_msqid64_ds {
struct compat_ipc64_perm msg_perm;
compat_time_t msg_stime;
compat_ulong_t __unused1;
compat_time_t msg_rtime;
compat_ulong_t __unused2;
compat_time_t msg_ctime;
compat_ulong_t __unused3;
compat_ulong_t msg_cbytes;
compat_ulong_t msg_qnum;
compat_ulong_t msg_qbytes;
compat_pid_t msg_lspid;
compat_pid_t msg_lrpid;
compat_ulong_t __unused4;
compat_ulong_t __unused5;
};
struct compat_shmid64_ds {
struct compat_ipc64_perm shm_perm;
compat_size_t shm_segsz;
compat_time_t shm_atime;
compat_ulong_t __unused1;
compat_time_t shm_dtime;
compat_ulong_t __unused2;
compat_time_t shm_ctime;
compat_ulong_t __unused3;
compat_pid_t shm_cpid;
compat_pid_t shm_lpid;
compat_ulong_t shm_nattch;
compat_ulong_t __unused4;
compat_ulong_t __unused5;
};
static inline int is_compat_task(void)
{
return test_thread_flag(TIF_32BIT);
}
static inline int is_compat_thread(struct thread_info *thread)
{
return test_ti_thread_flag(thread, TIF_32BIT);
}
#else /* !CONFIG_COMPAT */
static inline int is_compat_task(void)
{
return 0;
}
static inline int is_compat_thread(struct thread_info *thread)
{
return 0;
}
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#endif /* __ASM_COMPAT_H */
/*
* Copyright (C) 2012 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_SIGNAL32_H
#define __ASM_SIGNAL32_H
#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#define AARCH32_KERN_SIGRET_CODE_OFFSET 0x500
extern const compat_ulong_t aarch32_sigret_code[6];
int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
struct pt_regs *regs);
int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs);
void compat_setup_restart_syscall(struct pt_regs *regs);
#else
static inline int compat_setup_frame(int usid, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
return -ENOSYS;
}
static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs)
{
return -ENOSYS;
}
static inline void compat_setup_restart_syscall(struct pt_regs *regs)
{
}
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#endif /* __ASM_SIGNAL32_H */
This diff is collapsed.
/*
* Low-level user helpers placed in the vectors page for AArch32.
* Based on the kuser helpers in arch/arm/kernel/entry-armv.S.
*
* Copyright (C) 2005-2011 Nicolas Pitre <nico@fluxnic.net>
* Copyright (C) 2012 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* AArch32 user helpers.
*
* Each segment is 32-byte aligned and will be moved to the top of the high
* vector page. New segments (if ever needed) must be added in front of
* existing ones. This mechanism should be used only for things that are
* really small and justified, and not be abused freely.
*
* See Documentation/arm/kernel_user_helpers.txt for formal definitions.
*/
.align 5
.globl __kuser_helper_start
__kuser_helper_start:
__kuser_cmpxchg64: // 0xffff0f60
.inst 0xe92d00f0 // push {r4, r5, r6, r7}
.inst 0xe1c040d0 // ldrd r4, r5, [r0]
.inst 0xe1c160d0 // ldrd r6, r7, [r1]
.inst 0xf57ff05f // dmb sy
.inst 0xe1b20f9f // 1: ldrexd r0, r1, [r2]
.inst 0xe0303004 // eors r3, r0, r4
.inst 0x00313005 // eoreqs r3, r1, r5
.inst 0x01a23f96 // strexdeq r3, r6, [r2]
.inst 0x03330001 // teqeq r3, #1
.inst 0x0afffff9 // beq 1b
.inst 0xf57ff05f // dmb sy
.inst 0xe2730000 // rsbs r0, r3, #0
.inst 0xe8bd00f0 // pop {r4, r5, r6, r7}
.inst 0xe12fff1e // bx lr
.align 5
__kuser_memory_barrier: // 0xffff0fa0
.inst 0xf57ff05f // dmb sy
.inst 0xe12fff1e // bx lr
.align 5
__kuser_cmpxchg: // 0xffff0fc0
.inst 0xf57ff05f // dmb sy
.inst 0xe1923f9f // 1: ldrex r3, [r2]
.inst 0xe0533000 // subs r3, r3, r0
.inst 0x01823f91 // strexeq r3, r1, [r2]
.inst 0x03330001 // teqeq r3, #1
.inst 0x0afffffa // beq 1b
.inst 0xe2730000 // rsbs r0, r3, #0
.inst 0xeaffffef // b <__kuser_memory_barrier>
.align 5
__kuser_get_tls: // 0xffff0fe0
.inst 0xee1d0f70 // mrc p15, 0, r0, c13, c0, 3
.inst 0xe12fff1e // bx lr
.rep 5
.word 0
.endr
__kuser_helper_version: // 0xffff0ffc
.word ((__kuser_helper_end - __kuser_helper_start) >> 5)
.globl __kuser_helper_end
__kuser_helper_end:
This diff is collapsed.
/*
* Compat system call wrappers
*
* Copyright (C) 2012 ARM Ltd.
* Authors: Will Deacon <will.deacon@arm.com>
* Catalin Marinas <catalin.marinas@arm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
/*
* System call wrappers for the AArch32 compatibility layer.
*/
compat_sys_fork_wrapper:
mov x0, sp
b compat_sys_fork
ENDPROC(compat_sys_fork_wrapper)
compat_sys_vfork_wrapper:
mov x0, sp
b compat_sys_vfork
ENDPROC(compat_sys_vfork_wrapper)
compat_sys_execve_wrapper:
mov x3, sp
b compat_sys_execve
ENDPROC(compat_sys_execve_wrapper)
compat_sys_clone_wrapper:
mov x5, sp
b compat_sys_clone
ENDPROC(compat_sys_clone_wrapper)
compat_sys_sigreturn_wrapper:
mov x0, sp
mov x27, #0 // prevent syscall restart handling (why)
b compat_sys_sigreturn
ENDPROC(compat_sys_sigreturn_wrapper)
compat_sys_rt_sigreturn_wrapper:
mov x0, sp
mov x27, #0 // prevent syscall restart handling (why)
b compat_sys_rt_sigreturn
ENDPROC(compat_sys_rt_sigreturn_wrapper)
compat_sys_sigaltstack_wrapper:
ldr x2, [sp, #S_COMPAT_SP]
b compat_do_sigaltstack
ENDPROC(compat_sys_sigaltstack_wrapper)
compat_sys_statfs64_wrapper:
mov w3, #84
cmp w1, #88
csel w1, w3, w1, eq
b compat_sys_statfs64
ENDPROC(compat_sys_statfs64_wrapper)
compat_sys_fstatfs64_wrapper:
mov w3, #84
cmp w1, #88
csel w1, w3, w1, eq
b compat_sys_fstatfs64
ENDPROC(compat_sys_fstatfs64_wrapper)
/*
* Wrappers for AArch32 syscalls that either take 64-bit parameters
* in registers or that take 32-bit parameters which require sign
* extension.
*/
compat_sys_lseek_wrapper:
sxtw x1, w1
b sys_lseek
ENDPROC(compat_sys_lseek_wrapper)
compat_sys_pread64_wrapper:
orr x3, x4, x5, lsl #32
b sys_pread64
ENDPROC(compat_sys_pread64_wrapper)
compat_sys_pwrite64_wrapper:
orr x3, x4, x5, lsl #32
b sys_pwrite64
ENDPROC(compat_sys_pwrite64_wrapper)
compat_sys_truncate64_wrapper:
orr x1, x2, x3, lsl #32
b sys_truncate
ENDPROC(compat_sys_truncate64_wrapper)
compat_sys_ftruncate64_wrapper:
orr x1, x2, x3, lsl #32
b sys_ftruncate
ENDPROC(compat_sys_ftruncate64_wrapper)
compat_sys_readahead_wrapper:
orr x1, x2, x3, lsl #32
mov w2, w4
b sys_readahead
ENDPROC(compat_sys_readahead_wrapper)
compat_sys_lookup_dcookie:
orr x0, x0, x1, lsl #32
mov w1, w2
mov w2, w3
b sys_lookup_dcookie
ENDPROC(compat_sys_lookup_dcookie)
compat_sys_fadvise64_64_wrapper:
mov w6, w1
orr x1, x2, x3, lsl #32
orr x2, x4, x5, lsl #32
mov w3, w6
b sys_fadvise64_64
ENDPROC(compat_sys_fadvise64_64_wrapper)
compat_sys_sync_file_range2_wrapper:
orr x2, x2, x3, lsl #32
orr x3, x4, x5, lsl #32
b sys_sync_file_range2
ENDPROC(compat_sys_sync_file_range2_wrapper)
compat_sys_fallocate_wrapper:
orr x2, x2, x3, lsl #32
orr x3, x4, x5, lsl #32
b sys_fallocate
ENDPROC(compat_sys_fallocate_wrapper)
compat_sys_fanotify_mark_wrapper:
orr x2, x2, x3, lsl #32
mov w3, w4
mov w4, w5
b sys_fanotify_mark
ENDPROC(compat_sys_fanotify_mark_wrapper)
/*
* Use the compat system call wrappers.
*/
#define sys_fork compat_sys_fork_wrapper
#define sys_open compat_sys_open
#define sys_execve compat_sys_execve_wrapper
#define sys_lseek compat_sys_lseek_wrapper
#define sys_mount compat_sys_mount
#define sys_ptrace compat_sys_ptrace
#define sys_times compat_sys_times
#define sys_ioctl compat_sys_ioctl
#define sys_fcntl compat_sys_fcntl
#define sys_ustat compat_sys_ustat
#define sys_sigaction compat_sys_sigaction
#define sys_sigsuspend compat_sys_sigsuspend
#define sys_sigpending compat_sys_sigpending
#define sys_setrlimit compat_sys_setrlimit
#define sys_getrusage compat_sys_getrusage
#define sys_gettimeofday compat_sys_gettimeofday
#define sys_settimeofday compat_sys_settimeofday
#define sys_statfs compat_sys_statfs
#define sys_fstatfs compat_sys_fstatfs
#define sys_setitimer compat_sys_setitimer
#define sys_getitimer compat_sys_getitimer
#define sys_newstat compat_sys_newstat
#define sys_newlstat compat_sys_newlstat
#define sys_newfstat compat_sys_newfstat
#define sys_wait4 compat_sys_wait4
#define sys_sysinfo compat_sys_sysinfo
#define sys_sigreturn compat_sys_sigreturn_wrapper
#define sys_clone compat_sys_clone_wrapper
#define sys_adjtimex compat_sys_adjtimex
#define sys_sigprocmask compat_sys_sigprocmask
#define sys_getdents compat_sys_getdents
#define sys_select compat_sys_select
#define sys_readv compat_sys_readv
#define sys_writev compat_sys_writev
#define sys_sysctl compat_sys_sysctl
#define sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
#define sys_nanosleep compat_sys_nanosleep
#define sys_rt_sigreturn compat_sys_rt_sigreturn_wrapper
#define sys_rt_sigaction compat_sys_rt_sigaction
#define sys_rt_sigprocmask compat_sys_rt_sigprocmask
#define sys_rt_sigpending compat_sys_rt_sigpending
#define sys_rt_sigtimedwait compat_sys_rt_sigtimedwait
#define sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
#define sys_rt_sigsuspend compat_sys_rt_sigsuspend
#define sys_pread64 compat_sys_pread64_wrapper
#define sys_pwrite64 compat_sys_pwrite64_wrapper
#define sys_sigaltstack compat_sys_sigaltstack_wrapper
#define sys_sendfile compat_sys_sendfile
#define sys_vfork compat_sys_vfork_wrapper
#define sys_getrlimit compat_sys_getrlimit
#define sys_mmap2 sys_mmap_pgoff
#define sys_truncate64 compat_sys_truncate64_wrapper
#define sys_ftruncate64 compat_sys_ftruncate64_wrapper
#define sys_getdents64 compat_sys_getdents64
#define sys_fcntl64 compat_sys_fcntl64
#define sys_readahead compat_sys_readahead_wrapper
#define sys_futex compat_sys_futex
#define sys_sched_setaffinity compat_sys_sched_setaffinity
#define sys_sched_getaffinity compat_sys_sched_getaffinity
#define sys_io_setup compat_sys_io_setup
#define sys_io_getevents compat_sys_io_getevents
#define sys_io_submit compat_sys_io_submit
#define sys_lookup_dcookie compat_sys_lookup_dcookie
#define sys_timer_create compat_sys_timer_create
#define sys_timer_settime compat_sys_timer_settime
#define sys_timer_gettime compat_sys_timer_gettime
#define sys_clock_settime compat_sys_clock_settime
#define sys_clock_gettime compat_sys_clock_gettime
#define sys_clock_getres compat_sys_clock_getres
#define sys_clock_nanosleep compat_sys_clock_nanosleep
#define sys_statfs64 compat_sys_statfs64_wrapper
#define sys_fstatfs64 compat_sys_fstatfs64_wrapper
#define sys_utimes compat_sys_utimes
#define sys_fadvise64_64 compat_sys_fadvise64_64_wrapper
#define sys_mq_open compat_sys_mq_open
#define sys_mq_timedsend compat_sys_mq_timedsend
#define sys_mq_timedreceive compat_sys_mq_timedreceive
#define sys_mq_notify compat_sys_mq_notify
#define sys_mq_getsetattr compat_sys_mq_getsetattr
#define sys_waitid compat_sys_waitid
#define sys_recv compat_sys_recv
#define sys_recvfrom compat_sys_recvfrom
#define sys_setsockopt compat_sys_setsockopt
#define sys_getsockopt compat_sys_getsockopt
#define sys_sendmsg compat_sys_sendmsg
#define sys_recvmsg compat_sys_recvmsg
#define sys_semctl compat_sys_semctl
#define sys_msgsnd compat_sys_msgsnd
#define sys_msgrcv compat_sys_msgrcv
#define sys_msgctl compat_sys_msgctl
#define sys_shmat compat_sys_shmat
#define sys_shmctl compat_sys_shmctl
#define sys_keyctl compat_sys_keyctl
#define sys_semtimedop compat_sys_semtimedop
#define sys_mbind compat_sys_mbind
#define sys_get_mempolicy compat_sys_get_mempolicy
#define sys_set_mempolicy compat_sys_set_mempolicy
#define sys_openat compat_sys_openat
#define sys_futimesat compat_sys_futimesat
#define sys_pselect6 compat_sys_pselect6
#define sys_ppoll compat_sys_ppoll
#define sys_set_robust_list compat_sys_set_robust_list
#define sys_get_robust_list compat_sys_get_robust_list
#define sys_sync_file_range2 compat_sys_sync_file_range2_wrapper
#define sys_vmsplice compat_sys_vmsplice
#define sys_move_pages compat_sys_move_pages
#define sys_epoll_pwait compat_sys_epoll_pwait
#define sys_kexec_load compat_sys_kexec_load
#define sys_utimensat compat_sys_utimensat
#define sys_signalfd compat_sys_signalfd
#define sys_fallocate compat_sys_fallocate_wrapper
#define sys_timerfd_settime compat_sys_timerfd_settime
#define sys_timerfd_gettime compat_sys_timerfd_gettime
#define sys_signalfd4 compat_sys_signalfd4
#define sys_preadv compat_sys_preadv
#define sys_pwritev compat_sys_pwritev
#define sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
#define sys_recvmmsg compat_sys_recvmmsg
#define sys_fanotify_mark compat_sys_fanotify_mark_wrapper
#undef __SYSCALL
#define __SYSCALL(x, y) .quad y // x
#define __SYSCALL_COMPAT
/*
* The system calls table must be 4KB aligned.
*/
.align 12
ENTRY(compat_sys_call_table)
#include <asm/unistd.h>
/*
* Based on arch/arm/kernel/sys_arm.c
*
* Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
* Copyright (C) 1995, 1996 Russell King.
* Copyright (C) 2012 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define __SYSCALL_COMPAT
#include <linux/compat.h>
#include <linux/personality.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <asm/cacheflush.h>
#include <asm/unistd.h>
asmlinkage int compat_sys_fork(struct pt_regs *regs)
{
return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL);
}
asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp,
int __user *parent_tidptr, int tls_val,
int __user *child_tidptr, struct pt_regs *regs)
{
if (!newsp)
newsp = regs->compat_sp;
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
}
asmlinkage int compat_sys_vfork(struct pt_regs *regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp,
regs, 0, NULL, NULL);
}
asmlinkage int compat_sys_execve(const char __user *filenamei,
compat_uptr_t argv, compat_uptr_t envp,
struct pt_regs *regs)
{
int error;
char * filename;
filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp),
regs);
putname(filename);
out:
return error;
}
asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
struct compat_timespec __user *interval)
{
struct timespec t;
int ret;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
set_fs(old_fs);
if (put_compat_timespec(&t, interval))
return -EFAULT;
return ret;
}
asmlinkage int compat_sys_sendfile(int out_fd, int in_fd,
compat_off_t __user *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
off_t of;
if (offset && get_user(of, offset))
return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
count);
set_fs(old_fs);
if (offset && put_user(of, offset))
return -EFAULT;
return ret;
}
static inline void
do_compat_cache_op(unsigned long start, unsigned long end, int flags)
{
struct mm_struct *mm = current->active_mm;
struct vm_area_struct *vma;
if (end < start || flags)
return;
down_read(&mm->mmap_sem);
vma = find_vma(mm, start);
if (vma && vma->vm_start < end) {
if (start < vma->vm_start)
start = vma->vm_start;
if (end > vma->vm_end)
end = vma->vm_end;
up_read(&mm->mmap_sem);
__flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end));
return;
}
up_read(&mm->mmap_sem);
}
/*
* Handle all unrecognised system calls.
*/
long compat_arm_syscall(struct pt_regs *regs)
{
unsigned int no = regs->regs[7];
switch (no) {
/*
* Flush a region from virtual address 'r0' to virtual address 'r1'
* _exclusive_. There is no alignment requirement on either address;
* user space does not need to know the hardware cache layout.
*
* r2 contains flags. It should ALWAYS be passed as ZERO until it
* is defined to be something else. For now we ignore it, but may
* the fires of hell burn in your belly if you break this rule. ;)
*
* (at a later date, we may want to allow this call to not flush
* various aspects of the cache. Passing '0' will guarantee that
* everything necessary gets flushed to maintain consistency in
* the specified region).
*/
case __ARM_NR_compat_cacheflush:
do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
return 0;
case __ARM_NR_compat_set_tls:
current->thread.tp_value = regs->regs[0];
asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0]));
return 0;
default:
return -ENOSYS;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment