Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Access to user system call parameters and results
0004  *
0005  * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
0006  *
0007  * See asm-generic/syscall.h for descriptions of what we must do here.
0008  */
0009 
0010 #ifndef _ASM_SYSCALL_H
0011 #define _ASM_SYSCALL_H  1
0012 
0013 #include <uapi/linux/audit.h>
0014 #include <linux/sched.h>
0015 #include <linux/thread_info.h>
0016 
0017 /* ftrace syscalls requires exporting the sys_call_table */
0018 extern const unsigned long sys_call_table[];
0019 extern const unsigned long compat_sys_call_table[];
0020 
0021 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
0022 {
0023     /*
0024      * Note that we are returning an int here. That means 0xffffffff, ie.
0025      * 32-bit negative 1, will be interpreted as -1 on a 64-bit kernel.
0026      * This is important for seccomp so that compat tasks can set r0 = -1
0027      * to reject the syscall.
0028      */
0029     if (trap_is_syscall(regs))
0030         return regs->gpr[0];
0031     else
0032         return -1;
0033 }
0034 
0035 static inline void syscall_rollback(struct task_struct *task,
0036                     struct pt_regs *regs)
0037 {
0038     regs->gpr[3] = regs->orig_gpr3;
0039 }
0040 
0041 static inline long syscall_get_error(struct task_struct *task,
0042                      struct pt_regs *regs)
0043 {
0044     if (trap_is_scv(regs)) {
0045         unsigned long error = regs->gpr[3];
0046 
0047         return IS_ERR_VALUE(error) ? error : 0;
0048     } else {
0049         /*
0050          * If the system call failed,
0051          * regs->gpr[3] contains a positive ERRORCODE.
0052          */
0053         return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
0054     }
0055 }
0056 
0057 static inline long syscall_get_return_value(struct task_struct *task,
0058                         struct pt_regs *regs)
0059 {
0060     return regs->gpr[3];
0061 }
0062 
0063 static inline void syscall_set_return_value(struct task_struct *task,
0064                         struct pt_regs *regs,
0065                         int error, long val)
0066 {
0067     if (trap_is_scv(regs)) {
0068         regs->gpr[3] = (long) error ?: val;
0069     } else {
0070         /*
0071          * In the general case it's not obvious that we must deal with
0072          * CCR here, as the syscall exit path will also do that for us.
0073          * However there are some places, eg. the signal code, which
0074          * check ccr to decide if the value in r3 is actually an error.
0075          */
0076         if (error) {
0077             regs->ccr |= 0x10000000L;
0078             regs->gpr[3] = error;
0079         } else {
0080             regs->ccr &= ~0x10000000L;
0081             regs->gpr[3] = val;
0082         }
0083     }
0084 }
0085 
0086 static inline void syscall_get_arguments(struct task_struct *task,
0087                      struct pt_regs *regs,
0088                      unsigned long *args)
0089 {
0090     unsigned long val, mask = -1UL;
0091     unsigned int n = 6;
0092 
0093     if (is_tsk_32bit_task(task))
0094         mask = 0xffffffff;
0095 
0096     while (n--) {
0097         if (n == 0)
0098             val = regs->orig_gpr3;
0099         else
0100             val = regs->gpr[3 + n];
0101 
0102         args[n] = val & mask;
0103     }
0104 }
0105 
0106 static inline int syscall_get_arch(struct task_struct *task)
0107 {
0108     if (is_tsk_32bit_task(task))
0109         return AUDIT_ARCH_PPC;
0110     else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
0111         return AUDIT_ARCH_PPC64LE;
0112     else
0113         return AUDIT_ARCH_PPC64;
0114 }
0115 #endif  /* _ASM_SYSCALL_H */