syscall.h (3329B)
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Access to user system call parameters and results 4 * 5 * Copyright (C) 2008-2009 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_X86_SYSCALL_H 11#define _ASM_X86_SYSCALL_H 12 13#include <uapi/linux/audit.h> 14#include <linux/sched.h> 15#include <linux/err.h> 16#include <asm/thread_info.h> /* for TS_COMPAT */ 17#include <asm/unistd.h> 18 19typedef long (*sys_call_ptr_t)(const struct pt_regs *); 20extern const sys_call_ptr_t sys_call_table[]; 21 22#if defined(CONFIG_X86_32) 23#define ia32_sys_call_table sys_call_table 24#else 25/* 26 * These may not exist, but still put the prototypes in so we 27 * can use IS_ENABLED(). 28 */ 29extern const sys_call_ptr_t ia32_sys_call_table[]; 30extern const sys_call_ptr_t x32_sys_call_table[]; 31#endif 32 33/* 34 * Only the low 32 bits of orig_ax are meaningful, so we return int. 35 * This importantly ignores the high bits on 64-bit, so comparisons 36 * sign-extend the low 32 bits. 37 */ 38static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 39{ 40 return regs->orig_ax; 41} 42 43static inline void syscall_rollback(struct task_struct *task, 44 struct pt_regs *regs) 45{ 46 regs->ax = regs->orig_ax; 47} 48 49static inline long syscall_get_error(struct task_struct *task, 50 struct pt_regs *regs) 51{ 52 unsigned long error = regs->ax; 53#ifdef CONFIG_IA32_EMULATION 54 /* 55 * TS_COMPAT is set for 32-bit syscall entries and then 56 * remains set until we return to user mode. 57 */ 58 if (task->thread_info.status & (TS_COMPAT|TS_I386_REGS_POKED)) 59 /* 60 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO 61 * and will match correctly in comparisons. 62 */ 63 error = (long) (int) error; 64#endif 65 return IS_ERR_VALUE(error) ? error : 0; 66} 67 68static inline long syscall_get_return_value(struct task_struct *task, 69 struct pt_regs *regs) 70{ 71 return regs->ax; 72} 73 74static inline void syscall_set_return_value(struct task_struct *task, 75 struct pt_regs *regs, 76 int error, long val) 77{ 78 regs->ax = (long) error ?: val; 79} 80 81#ifdef CONFIG_X86_32 82 83static inline void syscall_get_arguments(struct task_struct *task, 84 struct pt_regs *regs, 85 unsigned long *args) 86{ 87 memcpy(args, ®s->bx, 6 * sizeof(args[0])); 88} 89 90static inline int syscall_get_arch(struct task_struct *task) 91{ 92 return AUDIT_ARCH_I386; 93} 94 95#else /* CONFIG_X86_64 */ 96 97static inline void syscall_get_arguments(struct task_struct *task, 98 struct pt_regs *regs, 99 unsigned long *args) 100{ 101# ifdef CONFIG_IA32_EMULATION 102 if (task->thread_info.status & TS_COMPAT) { 103 *args++ = regs->bx; 104 *args++ = regs->cx; 105 *args++ = regs->dx; 106 *args++ = regs->si; 107 *args++ = regs->di; 108 *args = regs->bp; 109 } else 110# endif 111 { 112 *args++ = regs->di; 113 *args++ = regs->si; 114 *args++ = regs->dx; 115 *args++ = regs->r10; 116 *args++ = regs->r8; 117 *args = regs->r9; 118 } 119} 120 121static inline int syscall_get_arch(struct task_struct *task) 122{ 123 /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ 124 return (IS_ENABLED(CONFIG_IA32_EMULATION) && 125 task->thread_info.status & TS_COMPAT) 126 ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; 127} 128 129void do_syscall_64(struct pt_regs *regs, int nr); 130void do_int80_syscall_32(struct pt_regs *regs); 131long do_fast_syscall_32(struct pt_regs *regs); 132 133#endif /* CONFIG_X86_32 */ 134 135#endif /* _ASM_X86_SYSCALL_H */