0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/sched.h>
0009 #include <linux/sched/mm.h>
0010 #include <linux/syscalls.h>
0011 #include <linux/uaccess.h>
0012 #include <asm/prctl.h> /* XXX This should get the constants from libc */
0013 #include <registers.h>
0014 #include <os.h>
0015
0016 long arch_prctl(struct task_struct *task, int option,
0017 unsigned long __user *arg2)
0018 {
0019 unsigned long *ptr = arg2, tmp;
0020 long ret;
0021 int pid = task->mm->context.id.u.pid;
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 switch (option) {
0037 case ARCH_SET_FS:
0038 case ARCH_SET_GS:
0039 ret = restore_pid_registers(pid, ¤t->thread.regs.regs);
0040 if (ret)
0041 return ret;
0042 break;
0043 case ARCH_GET_FS:
0044 case ARCH_GET_GS:
0045
0046
0047
0048
0049
0050
0051
0052
0053 ptr = &tmp;
0054 }
0055
0056 ret = os_arch_prctl(pid, option, ptr);
0057 if (ret)
0058 return ret;
0059
0060 switch (option) {
0061 case ARCH_SET_FS:
0062 current->thread.arch.fs = (unsigned long) ptr;
0063 ret = save_registers(pid, ¤t->thread.regs.regs);
0064 break;
0065 case ARCH_SET_GS:
0066 ret = save_registers(pid, ¤t->thread.regs.regs);
0067 break;
0068 case ARCH_GET_FS:
0069 ret = put_user(tmp, arg2);
0070 break;
0071 case ARCH_GET_GS:
0072 ret = put_user(tmp, arg2);
0073 break;
0074 }
0075
0076 return ret;
0077 }
0078
0079 SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
0080 {
0081 return arch_prctl(current, option, (unsigned long __user *) arg2);
0082 }
0083
0084 void arch_switch_to(struct task_struct *to)
0085 {
0086 if ((to->thread.arch.fs == 0) || (to->mm == NULL))
0087 return;
0088
0089 arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
0090 }
0091
0092 SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
0093 unsigned long, prot, unsigned long, flags,
0094 unsigned long, fd, unsigned long, off)
0095 {
0096 if (off & ~PAGE_MASK)
0097 return -EINVAL;
0098
0099 return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
0100 }