at v6.14 141 lines 3.6 kB view raw
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 19/* This is used purely for kernel/trace/trace_syscalls.c */ 20typedef long (*sys_call_ptr_t)(const struct pt_regs *); 21extern const sys_call_ptr_t sys_call_table[]; 22 23/* 24 * These may not exist, but still put the prototypes in so we 25 * can use IS_ENABLED(). 26 */ 27extern long ia32_sys_call(const struct pt_regs *, unsigned int nr); 28extern long x32_sys_call(const struct pt_regs *, unsigned int nr); 29extern long x64_sys_call(const struct pt_regs *, unsigned int nr); 30 31/* 32 * Only the low 32 bits of orig_ax are meaningful, so we return int. 33 * This importantly ignores the high bits on 64-bit, so comparisons 34 * sign-extend the low 32 bits. 35 */ 36static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 37{ 38 return regs->orig_ax; 39} 40 41static inline void syscall_rollback(struct task_struct *task, 42 struct pt_regs *regs) 43{ 44 regs->ax = regs->orig_ax; 45} 46 47static inline long syscall_get_error(struct task_struct *task, 48 struct pt_regs *regs) 49{ 50 unsigned long error = regs->ax; 51#ifdef CONFIG_IA32_EMULATION 52 /* 53 * TS_COMPAT is set for 32-bit syscall entries and then 54 * remains set until we return to user mode. 55 */ 56 if (task->thread_info.status & (TS_COMPAT|TS_I386_REGS_POKED)) 57 /* 58 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO 59 * and will match correctly in comparisons. 60 */ 61 error = (long) (int) error; 62#endif 63 return IS_ERR_VALUE(error) ? error : 0; 64} 65 66static inline long syscall_get_return_value(struct task_struct *task, 67 struct pt_regs *regs) 68{ 69 return regs->ax; 70} 71 72static inline void syscall_set_return_value(struct task_struct *task, 73 struct pt_regs *regs, 74 int error, long val) 75{ 76 regs->ax = (long) error ?: val; 77} 78 79#ifdef CONFIG_X86_32 80 81static inline void syscall_get_arguments(struct task_struct *task, 82 struct pt_regs *regs, 83 unsigned long *args) 84{ 85 args[0] = regs->bx; 86 args[1] = regs->cx; 87 args[2] = regs->dx; 88 args[3] = regs->si; 89 args[4] = regs->di; 90 args[5] = regs->bp; 91} 92 93static inline int syscall_get_arch(struct task_struct *task) 94{ 95 return AUDIT_ARCH_I386; 96} 97 98#else /* CONFIG_X86_64 */ 99 100static inline void syscall_get_arguments(struct task_struct *task, 101 struct pt_regs *regs, 102 unsigned long *args) 103{ 104# ifdef CONFIG_IA32_EMULATION 105 if (task->thread_info.status & TS_COMPAT) { 106 *args++ = regs->bx; 107 *args++ = regs->cx; 108 *args++ = regs->dx; 109 *args++ = regs->si; 110 *args++ = regs->di; 111 *args = regs->bp; 112 } else 113# endif 114 { 115 *args++ = regs->di; 116 *args++ = regs->si; 117 *args++ = regs->dx; 118 *args++ = regs->r10; 119 *args++ = regs->r8; 120 *args = regs->r9; 121 } 122} 123 124static inline int syscall_get_arch(struct task_struct *task) 125{ 126 /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ 127 return (IS_ENABLED(CONFIG_IA32_EMULATION) && 128 task->thread_info.status & TS_COMPAT) 129 ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; 130} 131 132bool do_syscall_64(struct pt_regs *regs, int nr); 133void do_int80_emulation(struct pt_regs *regs); 134 135#endif /* CONFIG_X86_32 */ 136 137void do_int80_syscall_32(struct pt_regs *regs); 138bool do_fast_syscall_32(struct pt_regs *regs); 139bool do_SYSENTER_32(struct pt_regs *regs); 140 141#endif /* _ASM_X86_SYSCALL_H */