Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ASM_SPARC_SYSCALL_H #define __ASM_SPARC_SYSCALL_H #include <uapi/linux/audit.h> #include <linux/kernel.h> #include <linux/compat.h> #include <linux/sched.h> #include <asm/ptrace.h> #include <asm/thread_info.h> /* * The syscall table always contains 32 bit pointers since we know that the * address of the function to be called is (way) below 4GB. So the "int" * type here is what we want [need] for both 32 bit and 64 bit systems. */ extern const unsigned int sys_call_table[]; /* The system call number is given by the user in %g1 */ static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { int syscall_p = pt_regs_is_syscall(regs); return (syscall_p ? regs->u_regs[UREG_G1] : -1L); } static inline void syscall_rollback(struct task_struct *task, struct pt_regs *regs) { /* XXX This needs some thought. On Sparc we don't * XXX save away the original %o0 value somewhere. * XXX Instead we hold it in register %l5 at the top * XXX level trap frame and pass this down to the signal * XXX dispatch code which is the only place that value * XXX ever was needed. */ } #ifdef CONFIG_SPARC32 static inline bool syscall_has_error(struct pt_regs *regs) { return (regs->psr & PSR_C) ? true : false; } static inline void syscall_set_error(struct pt_regs *regs) { regs->psr |= PSR_C; } static inline void syscall_clear_error(struct pt_regs *regs) { regs->psr &= ~PSR_C; } #else static inline bool syscall_has_error(struct pt_regs *regs) { return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; } static inline void syscall_set_error(struct pt_regs *regs) { regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); } static inline void syscall_clear_error(struct pt_regs *regs) { regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); } #endif static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { long val = regs->u_regs[UREG_I0]; return (syscall_has_error(regs) ? -val : 0); } static inline long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { long val = regs->u_regs[UREG_I0]; return val; } static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { if (error) { syscall_set_error(regs); regs->u_regs[UREG_I0] = -error; } else { syscall_clear_error(regs); regs->u_regs[UREG_I0] = val; } } static inline void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, unsigned long *args) { int zero_extend = 0; unsigned int j; unsigned int n = 6; #ifdef CONFIG_SPARC64 if (test_tsk_thread_flag(task, TIF_32BIT)) zero_extend = 1; #endif for (j = 0; j < n; j++) { unsigned long val = regs->u_regs[UREG_I0 + j]; if (zero_extend) args[j] = (u32) val; else args[j] = val; } } static inline int syscall_get_arch(struct task_struct *task) { #if defined(CONFIG_SPARC64) && defined(CONFIG_COMPAT) return test_tsk_thread_flag(task, TIF_32BIT) ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64; #elif defined(CONFIG_SPARC64) return AUDIT_ARCH_SPARC64; #else return AUDIT_ARCH_SPARC; #endif } #endif /* __ASM_SPARC_SYSCALL_H */ |