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

scall64-o32.S (5267B)


      1/*
      2 * This file is subject to the terms and conditions of the GNU General Public
      3 * License.  See the file "COPYING" in the main directory of this archive
      4 * for more details.
      5 *
      6 * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
      7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
      8 * Copyright (C) 2001 MIPS Technologies, Inc.
      9 * Copyright (C) 2004 Thiemo Seufer
     10 *
     11 * Hairy, the userspace application uses a different argument passing
     12 * convention than the kernel, so we have to translate things from o32
     13 * to ABI64 calling convention.	 64-bit syscalls are also processed
     14 * here for now.
     15 */
     16#include <linux/errno.h>
     17#include <asm/asm.h>
     18#include <asm/asmmacro.h>
     19#include <asm/irqflags.h>
     20#include <asm/mipsregs.h>
     21#include <asm/regdef.h>
     22#include <asm/stackframe.h>
     23#include <asm/thread_info.h>
     24#include <asm/unistd.h>
     25#include <asm/sysmips.h>
     26
     27	.align	5
     28NESTED(handle_sys, PT_SIZE, sp)
     29	.set	noat
     30	SAVE_SOME
     31	TRACE_IRQS_ON_RELOAD
     32	STI
     33	.set	at
     34	ld	t1, PT_EPC(sp)		# skip syscall on return
     35
     36	dsubu	t0, v0, __NR_O32_Linux	# check syscall number
     37	sltiu	t0, t0, __NR_O32_Linux_syscalls
     38	daddiu	t1, 4			# skip to next instruction
     39	sd	t1, PT_EPC(sp)
     40	beqz	t0, not_o32_scall
     41#if 0
     42 SAVE_ALL
     43 move a1, v0
     44 ASM_PRINT("Scall %ld\n")
     45 RESTORE_ALL
     46#endif
     47
     48	/* We don't want to stumble over broken sign extensions from
     49	   userland. O32 does never use the upper half. */
     50	sll	a0, a0, 0
     51	sll	a1, a1, 0
     52	sll	a2, a2, 0
     53	sll	a3, a3, 0
     54
     55	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
     56
     57	/*
     58	 * More than four arguments.  Try to deal with it by copying the
     59	 * stack arguments from the user stack to the kernel stack.
     60	 * This Sucks (TM).
     61	 *
     62	 * We intentionally keep the kernel stack a little below the top of
     63	 * userspace so we don't have to do a slower byte accurate check here.
     64	 */
     65	ld	t0, PT_R29(sp)		# get old user stack pointer
     66	daddu	t1, t0, 32
     67	bltz	t1, bad_stack
     68
     69load_a4: lw	a4, 16(t0)		# argument #5 from usp
     70load_a5: lw	a5, 20(t0)		# argument #6 from usp
     71load_a6: lw	a6, 24(t0)		# argument #7 from usp
     72load_a7: lw	a7, 28(t0)		# argument #8 from usp
     73loads_done:
     74
     75	.section __ex_table,"a"
     76	PTR_WD	load_a4, bad_stack_a4
     77	PTR_WD	load_a5, bad_stack_a5
     78	PTR_WD	load_a6, bad_stack_a6
     79	PTR_WD	load_a7, bad_stack_a7
     80	.previous
     81
     82	li	t1, _TIF_WORK_SYSCALL_ENTRY
     83	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
     84	and	t0, t1, t0
     85	bnez	t0, trace_a_syscall
     86
     87syscall_common:
     88	dsll	t0, v0, 3		# offset into table
     89	ld	t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
     90
     91	jalr	t2			# Do The Real Thing (TM)
     92
     93	li	t0, -EMAXERRNO - 1	# error?
     94	sltu	t0, t0, v0
     95	sd	t0, PT_R7(sp)		# set error flag
     96	beqz	t0, 1f
     97
     98	ld	t1, PT_R2(sp)		# syscall number
     99	dnegu	v0			# error
    100	sd	t1, PT_R0(sp)		# save it for syscall restarting
    1011:	sd	v0, PT_R2(sp)		# result
    102
    103o32_syscall_exit:
    104	j	syscall_exit_partial
    105
    106/* ------------------------------------------------------------------------ */
    107
    108trace_a_syscall:
    109	SAVE_STATIC
    110	sd	a4, PT_R8(sp)		# Save argument registers
    111	sd	a5, PT_R9(sp)
    112	sd	a6, PT_R10(sp)
    113	sd	a7, PT_R11(sp)		# For indirect syscalls
    114
    115	move	a0, sp
    116	/*
    117	 * absolute syscall number is in v0 unless we called syscall(__NR_###)
    118	 * where the real syscall number is in a0
    119	 * note: NR_syscall is the first O32 syscall but the macro is
    120	 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
    121	 * therefore __NR_O32_Linux is used (4000)
    122	 */
    123	.set	push
    124	.set	reorder
    125	subu	t1, v0,  __NR_O32_Linux
    126	move	a1, v0
    127	bnez	t1, 1f /* __NR_syscall at offset 0 */
    128	ld	a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
    129	.set	pop
    130
    1311:	jal	syscall_trace_enter
    132
    133	bltz	v0, 1f			# seccomp failed? Skip syscall
    134
    135	RESTORE_STATIC
    136	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
    137	ld	a0, PT_R4(sp)		# Restore argument registers
    138	ld	a1, PT_R5(sp)
    139	ld	a2, PT_R6(sp)
    140	ld	a3, PT_R7(sp)
    141	ld	a4, PT_R8(sp)
    142	ld	a5, PT_R9(sp)
    143	ld	a6, PT_R10(sp)
    144	ld	a7, PT_R11(sp)		# For indirect syscalls
    145
    146	dsubu	t0, v0, __NR_O32_Linux	# check (new) syscall number
    147	sltiu	t0, t0, __NR_O32_Linux_syscalls
    148	beqz	t0, not_o32_scall
    149
    150	j	syscall_common
    151
    1521:	j	syscall_exit
    153
    154/* ------------------------------------------------------------------------ */
    155
    156	/*
    157	 * The stackpointer for a call with more than 4 arguments is bad.
    158	 */
    159bad_stack:
    160	li	v0, EFAULT
    161	sd	v0, PT_R2(sp)
    162	li	t0, 1			# set error flag
    163	sd	t0, PT_R7(sp)
    164	j	o32_syscall_exit
    165
    166bad_stack_a4:
    167	li	a4, 0
    168	b	load_a5
    169
    170bad_stack_a5:
    171	li	a5, 0
    172	b	load_a6
    173
    174bad_stack_a6:
    175	li	a6, 0
    176	b	load_a7
    177
    178bad_stack_a7:
    179	li	a7, 0
    180	b	loads_done
    181
    182not_o32_scall:
    183	/*
    184	 * This is not an o32 compatibility syscall, pass it on
    185	 * to the 64-bit syscall handlers.
    186	 */
    187#ifdef CONFIG_MIPS32_N32
    188	j	handle_sysn32
    189#else
    190	j	handle_sys64
    191#endif
    192	END(handle_sys)
    193
    194LEAF(sys32_syscall)
    195	subu	t0, a0, __NR_O32_Linux	# check syscall number
    196	sltiu	v0, t0, __NR_O32_Linux_syscalls
    197	beqz	t0, einval		# do not recurse
    198	dsll	t1, t0, 3
    199	beqz	v0, einval
    200	ld	t2, sys32_call_table(t1)		# syscall routine
    201
    202	move	a0, a1			# shift argument registers
    203	move	a1, a2
    204	move	a2, a3
    205	move	a3, a4
    206	move	a4, a5
    207	move	a5, a6
    208	move	a6, a7
    209	jr	t2
    210	/* Unreached */
    211
    212einval: li	v0, -ENOSYS
    213	jr	ra
    214	END(sys32_syscall)
    215
    216#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, compat)
    217#define __SYSCALL(nr, entry)	PTR_WD entry
    218	.align	3
    219	.type	sys32_call_table,@object
    220EXPORT(sys32_call_table)
    221#include <asm/syscall_table_o32.h>