cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

syscall.h (3702B)


      1/*
      2 * Access to user system call parameters and results
      3 *
      4 * This file is subject to the terms and conditions of the GNU General Public
      5 * License.  See the file "COPYING" in the main directory of this archive
      6 * for more details.
      7 *
      8 * See asm-generic/syscall.h for descriptions of what we must do here.
      9 *
     10 * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
     11 */
     12
     13#ifndef __ASM_MIPS_SYSCALL_H
     14#define __ASM_MIPS_SYSCALL_H
     15
     16#include <linux/compiler.h>
     17#include <uapi/linux/audit.h>
     18#include <linux/elf-em.h>
     19#include <linux/kernel.h>
     20#include <linux/sched.h>
     21#include <linux/uaccess.h>
     22#include <asm/ptrace.h>
     23#include <asm/unistd.h>
     24
     25#ifndef __NR_syscall /* Only defined if _MIPS_SIM == _MIPS_SIM_ABI32 */
     26#define __NR_syscall 4000
     27#endif
     28
     29static inline bool mips_syscall_is_indirect(struct task_struct *task,
     30					    struct pt_regs *regs)
     31{
     32	/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
     33	return (IS_ENABLED(CONFIG_32BIT) ||
     34		test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
     35		(regs->regs[2] == __NR_syscall);
     36}
     37
     38static inline long syscall_get_nr(struct task_struct *task,
     39				  struct pt_regs *regs)
     40{
     41	return current_thread_info()->syscall;
     42}
     43
     44static inline void mips_syscall_update_nr(struct task_struct *task,
     45					  struct pt_regs *regs)
     46{
     47	/*
     48	 * v0 is the system call number, except for O32 ABI syscall(), where it
     49	 * ends up in a0.
     50	 */
     51	if (mips_syscall_is_indirect(task, regs))
     52		task_thread_info(task)->syscall = regs->regs[4];
     53	else
     54		task_thread_info(task)->syscall = regs->regs[2];
     55}
     56
     57static inline void mips_get_syscall_arg(unsigned long *arg,
     58	struct task_struct *task, struct pt_regs *regs, unsigned int n)
     59{
     60	unsigned long usp __maybe_unused = regs->regs[29];
     61
     62	switch (n) {
     63	case 0: case 1: case 2: case 3:
     64		*arg = regs->regs[4 + n];
     65
     66		return;
     67
     68#ifdef CONFIG_32BIT
     69	case 4: case 5: case 6: case 7:
     70		get_user(*arg, (int *)usp + n);
     71		return;
     72#endif
     73
     74#ifdef CONFIG_64BIT
     75	case 4: case 5: case 6: case 7:
     76#ifdef CONFIG_MIPS32_O32
     77		if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
     78			get_user(*arg, (int *)usp + n);
     79		else
     80#endif
     81			*arg = regs->regs[4 + n];
     82
     83		return;
     84#endif
     85
     86	default:
     87		BUG();
     88	}
     89
     90	unreachable();
     91}
     92
     93static inline long syscall_get_error(struct task_struct *task,
     94				     struct pt_regs *regs)
     95{
     96	return regs->regs[7] ? -regs->regs[2] : 0;
     97}
     98
     99static inline long syscall_get_return_value(struct task_struct *task,
    100					    struct pt_regs *regs)
    101{
    102	return regs->regs[2];
    103}
    104
    105static inline void syscall_rollback(struct task_struct *task,
    106				    struct pt_regs *regs)
    107{
    108	/* Do nothing */
    109}
    110
    111static inline void syscall_set_return_value(struct task_struct *task,
    112					    struct pt_regs *regs,
    113					    int error, long val)
    114{
    115	if (error) {
    116		regs->regs[2] = -error;
    117		regs->regs[7] = 1;
    118	} else {
    119		regs->regs[2] = val;
    120		regs->regs[7] = 0;
    121	}
    122}
    123
    124static inline void syscall_get_arguments(struct task_struct *task,
    125					 struct pt_regs *regs,
    126					 unsigned long *args)
    127{
    128	unsigned int i = 0;
    129	unsigned int n = 6;
    130
    131	/* O32 ABI syscall() */
    132	if (mips_syscall_is_indirect(task, regs))
    133		i++;
    134
    135	while (n--)
    136		mips_get_syscall_arg(args++, task, regs, i++);
    137}
    138
    139extern const unsigned long sys_call_table[];
    140extern const unsigned long sys32_call_table[];
    141extern const unsigned long sysn32_call_table[];
    142
    143static inline int syscall_get_arch(struct task_struct *task)
    144{
    145	int arch = AUDIT_ARCH_MIPS;
    146#ifdef CONFIG_64BIT
    147	if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) {
    148		arch |= __AUDIT_ARCH_64BIT;
    149		/* N32 sets only TIF_32BIT_ADDR */
    150		if (test_tsk_thread_flag(task, TIF_32BIT_ADDR))
    151			arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
    152	}
    153#endif
    154#if defined(__LITTLE_ENDIAN)
    155	arch |=  __AUDIT_ARCH_LE;
    156#endif
    157	return arch;
    158}
    159
    160#endif	/* __ASM_MIPS_SYSCALL_H */