linux/arch/powerpc/include/asm/syscall.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Access to user system call parameters and results
   4 *
   5 * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
   6 *
   7 * See asm-generic/syscall.h for descriptions of what we must do here.
   8 */
   9
  10#ifndef _ASM_SYSCALL_H
  11#define _ASM_SYSCALL_H  1
  12
  13#include <uapi/linux/audit.h>
  14#include <linux/sched.h>
  15#include <linux/thread_info.h>
  16
  17/* ftrace syscalls requires exporting the sys_call_table */
  18extern const unsigned long sys_call_table[];
  19extern const unsigned long compat_sys_call_table[];
  20
  21static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
  22{
  23        /*
  24         * Note that we are returning an int here. That means 0xffffffff, ie.
  25         * 32-bit negative 1, will be interpreted as -1 on a 64-bit kernel.
  26         * This is important for seccomp so that compat tasks can set r0 = -1
  27         * to reject the syscall.
  28         */
  29        if (trap_is_syscall(regs))
  30                return regs->gpr[0];
  31        else
  32                return -1;
  33}
  34
  35static inline void syscall_rollback(struct task_struct *task,
  36                                    struct pt_regs *regs)
  37{
  38        regs->gpr[3] = regs->orig_gpr3;
  39}
  40
  41static inline long syscall_get_error(struct task_struct *task,
  42                                     struct pt_regs *regs)
  43{
  44        if (trap_is_scv(regs)) {
  45                unsigned long error = regs->gpr[3];
  46
  47                return IS_ERR_VALUE(error) ? error : 0;
  48        } else {
  49                /*
  50                 * If the system call failed,
  51                 * regs->gpr[3] contains a positive ERRORCODE.
  52                 */
  53                return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
  54        }
  55}
  56
  57static inline long syscall_get_return_value(struct task_struct *task,
  58                                            struct pt_regs *regs)
  59{
  60        return regs->gpr[3];
  61}
  62
  63static inline void syscall_set_return_value(struct task_struct *task,
  64                                            struct pt_regs *regs,
  65                                            int error, long val)
  66{
  67        if (trap_is_scv(regs)) {
  68                regs->gpr[3] = (long) error ?: val;
  69        } else {
  70                /*
  71                 * In the general case it's not obvious that we must deal with
  72                 * CCR here, as the syscall exit path will also do that for us.
  73                 * However there are some places, eg. the signal code, which
  74                 * check ccr to decide if the value in r3 is actually an error.
  75                 */
  76                if (error) {
  77                        regs->ccr |= 0x10000000L;
  78                        regs->gpr[3] = error;
  79                } else {
  80                        regs->ccr &= ~0x10000000L;
  81                        regs->gpr[3] = val;
  82                }
  83        }
  84}
  85
  86static inline void syscall_get_arguments(struct task_struct *task,
  87                                         struct pt_regs *regs,
  88                                         unsigned long *args)
  89{
  90        unsigned long val, mask = -1UL;
  91        unsigned int n = 6;
  92
  93#ifdef CONFIG_COMPAT
  94        if (test_tsk_thread_flag(task, TIF_32BIT))
  95                mask = 0xffffffff;
  96#endif
  97        while (n--) {
  98                if (n == 0)
  99                        val = regs->orig_gpr3;
 100                else
 101                        val = regs->gpr[3 + n];
 102
 103                args[n] = val & mask;
 104        }
 105}
 106
 107static inline void syscall_set_arguments(struct task_struct *task,
 108                                         struct pt_regs *regs,
 109                                         const unsigned long *args)
 110{
 111        memcpy(&regs->gpr[3], args, 6 * sizeof(args[0]));
 112
 113        /* Also copy the first argument into orig_gpr3 */
 114        regs->orig_gpr3 = args[0];
 115}
 116
 117static inline int syscall_get_arch(struct task_struct *task)
 118{
 119        int arch;
 120
 121        if (IS_ENABLED(CONFIG_PPC64) && !test_tsk_thread_flag(task, TIF_32BIT))
 122                arch = AUDIT_ARCH_PPC64;
 123        else
 124                arch = AUDIT_ARCH_PPC;
 125
 126#ifdef __LITTLE_ENDIAN__
 127        arch |= __AUDIT_ARCH_LE;
 128#endif
 129        return arch;
 130}
 131#endif  /* _ASM_SYSCALL_H */
 132