linux/arch/x86/include/asm/syscall.h
<<
>>
Prefs
   1/*
   2 * Access to user system call parameters and results
   3 *
   4 * Copyright (C) 2008-2009 Red Hat, Inc.  All rights reserved.
   5 *
   6 * This copyrighted material is made available to anyone wishing to use,
   7 * modify, copy, or redistribute it subject to the terms and conditions
   8 * of the GNU General Public License v.2.
   9 *
  10 * See asm-generic/syscall.h for descriptions of what we must do here.
  11 */
  12
  13#ifndef _ASM_X86_SYSCALL_H
  14#define _ASM_X86_SYSCALL_H
  15
  16#include <uapi/linux/audit.h>
  17#include <linux/sched.h>
  18#include <linux/err.h>
  19#include <asm/asm-offsets.h>    /* For NR_syscalls */
  20#include <asm/thread_info.h>    /* for TS_COMPAT */
  21#include <asm/unistd.h>
  22
  23typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long,
  24                                          unsigned long, unsigned long,
  25                                          unsigned long, unsigned long);
  26extern const sys_call_ptr_t sys_call_table[];
  27
  28#if defined(CONFIG_X86_32)
  29#define ia32_sys_call_table sys_call_table
  30#define __NR_syscall_compat_max __NR_syscall_max
  31#define IA32_NR_syscalls NR_syscalls
  32#endif
  33
  34#if defined(CONFIG_IA32_EMULATION)
  35extern const sys_call_ptr_t ia32_sys_call_table[];
  36#endif
  37
  38/*
  39 * Only the low 32 bits of orig_ax are meaningful, so we return int.
  40 * This importantly ignores the high bits on 64-bit, so comparisons
  41 * sign-extend the low 32 bits.
  42 */
  43static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
  44{
  45        return regs->orig_ax;
  46}
  47
  48static inline void syscall_rollback(struct task_struct *task,
  49                                    struct pt_regs *regs)
  50{
  51        regs->ax = regs->orig_ax;
  52}
  53
  54static inline long syscall_get_error(struct task_struct *task,
  55                                     struct pt_regs *regs)
  56{
  57        unsigned long error = regs->ax;
  58#ifdef CONFIG_IA32_EMULATION
  59        /*
  60         * TS_COMPAT is set for 32-bit syscall entries and then
  61         * remains set until we return to user mode.
  62         */
  63        if (task->thread.status & (TS_COMPAT|TS_I386_REGS_POKED))
  64                /*
  65                 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
  66                 * and will match correctly in comparisons.
  67                 */
  68                error = (long) (int) error;
  69#endif
  70        return IS_ERR_VALUE(error) ? error : 0;
  71}
  72
  73static inline long syscall_get_return_value(struct task_struct *task,
  74                                            struct pt_regs *regs)
  75{
  76        return regs->ax;
  77}
  78
  79static inline void syscall_set_return_value(struct task_struct *task,
  80                                            struct pt_regs *regs,
  81                                            int error, long val)
  82{
  83        regs->ax = (long) error ?: val;
  84}
  85
  86#ifdef CONFIG_X86_32
  87
  88static inline void syscall_get_arguments(struct task_struct *task,
  89                                         struct pt_regs *regs,
  90                                         unsigned int i, unsigned int n,
  91                                         unsigned long *args)
  92{
  93        BUG_ON(i + n > 6);
  94        memcpy(args, &regs->bx + i, n * sizeof(args[0]));
  95}
  96
  97static inline void syscall_set_arguments(struct task_struct *task,
  98                                         struct pt_regs *regs,
  99                                         unsigned int i, unsigned int n,
 100                                         const unsigned long *args)
 101{
 102        BUG_ON(i + n > 6);
 103        memcpy(&regs->bx + i, args, n * sizeof(args[0]));
 104}
 105
 106static inline int syscall_get_arch(void)
 107{
 108        return AUDIT_ARCH_I386;
 109}
 110
 111#else    /* CONFIG_X86_64 */
 112
 113static inline void syscall_get_arguments(struct task_struct *task,
 114                                         struct pt_regs *regs,
 115                                         unsigned int i, unsigned int n,
 116                                         unsigned long *args)
 117{
 118# ifdef CONFIG_IA32_EMULATION
 119        if (task->thread.status & TS_COMPAT)
 120                switch (i) {
 121                case 0:
 122                        if (!n--) break;
 123                        *args++ = regs->bx;
 124                case 1:
 125                        if (!n--) break;
 126                        *args++ = regs->cx;
 127                case 2:
 128                        if (!n--) break;
 129                        *args++ = regs->dx;
 130                case 3:
 131                        if (!n--) break;
 132                        *args++ = regs->si;
 133                case 4:
 134                        if (!n--) break;
 135                        *args++ = regs->di;
 136                case 5:
 137                        if (!n--) break;
 138                        *args++ = regs->bp;
 139                case 6:
 140                        if (!n--) break;
 141                default:
 142                        BUG();
 143                        break;
 144                }
 145        else
 146# endif
 147                switch (i) {
 148                case 0:
 149                        if (!n--) break;
 150                        *args++ = regs->di;
 151                case 1:
 152                        if (!n--) break;
 153                        *args++ = regs->si;
 154                case 2:
 155                        if (!n--) break;
 156                        *args++ = regs->dx;
 157                case 3:
 158                        if (!n--) break;
 159                        *args++ = regs->r10;
 160                case 4:
 161                        if (!n--) break;
 162                        *args++ = regs->r8;
 163                case 5:
 164                        if (!n--) break;
 165                        *args++ = regs->r9;
 166                case 6:
 167                        if (!n--) break;
 168                default:
 169                        BUG();
 170                        break;
 171                }
 172}
 173
 174static inline void syscall_set_arguments(struct task_struct *task,
 175                                         struct pt_regs *regs,
 176                                         unsigned int i, unsigned int n,
 177                                         const unsigned long *args)
 178{
 179# ifdef CONFIG_IA32_EMULATION
 180        if (task->thread.status & TS_COMPAT)
 181                switch (i) {
 182                case 0:
 183                        if (!n--) break;
 184                        regs->bx = *args++;
 185                case 1:
 186                        if (!n--) break;
 187                        regs->cx = *args++;
 188                case 2:
 189                        if (!n--) break;
 190                        regs->dx = *args++;
 191                case 3:
 192                        if (!n--) break;
 193                        regs->si = *args++;
 194                case 4:
 195                        if (!n--) break;
 196                        regs->di = *args++;
 197                case 5:
 198                        if (!n--) break;
 199                        regs->bp = *args++;
 200                case 6:
 201                        if (!n--) break;
 202                default:
 203                        BUG();
 204                        break;
 205                }
 206        else
 207# endif
 208                switch (i) {
 209                case 0:
 210                        if (!n--) break;
 211                        regs->di = *args++;
 212                case 1:
 213                        if (!n--) break;
 214                        regs->si = *args++;
 215                case 2:
 216                        if (!n--) break;
 217                        regs->dx = *args++;
 218                case 3:
 219                        if (!n--) break;
 220                        regs->r10 = *args++;
 221                case 4:
 222                        if (!n--) break;
 223                        regs->r8 = *args++;
 224                case 5:
 225                        if (!n--) break;
 226                        regs->r9 = *args++;
 227                case 6:
 228                        if (!n--) break;
 229                default:
 230                        BUG();
 231                        break;
 232                }
 233}
 234
 235static inline int syscall_get_arch(void)
 236{
 237        /* x32 tasks should be considered AUDIT_ARCH_X86_64. */
 238        return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
 239}
 240#endif  /* CONFIG_X86_32 */
 241
 242#endif  /* _ASM_X86_SYSCALL_H */
 243