linux_dsm_epyc7002/arch/sh/kernel/cpu/sh2a/entry.S
Rich Felker 3623d13821 sh: provide unified syscall trap compatible with all SH models
Historically SH-2 Linux (and originally uClinux) used a syscall
calling convention incompatible with the established SH-3/4 Linux ABI.
This choice was made because the trap range used by the existing ABI,
0x10-0x17, overlaps with the hardware exception/interrupt trap range
reserved by SH-2, and in particular, with the SH-2A divide-by-zero and
division-overflow exceptions.

Despite the documented syscall convention using the low bits of the
trap number to signal the number of arguments the kernel should
expect, no version of the kernel has ever used this information, nor
is it useful; all of the registers need to be saved anyway. Therefore,
it is possible to pick a new trap number, 0x1f, that is both supported
by all existing SH-3/4 kernels and unassigned as a hardware trap in
the SH-2 range. This makes it possible to produce SH-2 application
binaries that are forwards-compatible with running on SH-3/4 kernels
and to treat SH as a unified platform with varying ISA support levels
rather than multiple gratuitously-incompatible platforms.

This patch adjusts the range checking SH-2 and SH-2A kernels make for
the syscall trap to accept the range 0x1f-0x2f rather than just
0x20-0x2f. As a result, trap 0x1f now acts as a syscall for all SH
models.

Signed-off-by: Rich Felker <dalias@libc.org>
2016-03-17 19:46:06 +00:00

251 lines
5.0 KiB
ArmAsm

/*
* arch/sh/kernel/cpu/sh2a/entry.S
*
* The SH-2A exception entry
*
* Copyright (C) 2008 Yoshinori Sato
* Based on arch/sh/kernel/cpu/sh2/entry.S
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <cpu/mmu_context.h>
#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/page.h>
/* Offsets to the stack */
OFF_R0 = 0 /* Return value. New ABI also arg4 */
OFF_R1 = 4 /* New ABI: arg5 */
OFF_R2 = 8 /* New ABI: arg6 */
OFF_R3 = 12 /* New ABI: syscall_nr */
OFF_R4 = 16 /* New ABI: arg0 */
OFF_R5 = 20 /* New ABI: arg1 */
OFF_R6 = 24 /* New ABI: arg2 */
OFF_R7 = 28 /* New ABI: arg3 */
OFF_SP = (15*4)
OFF_PC = (16*4)
OFF_SR = (16*4+2*4)
OFF_TRA = (16*4+6*4)
#include <asm/entry-macros.S>
ENTRY(exception_handler)
! stack
! r0 <- point sp
! r1
! pc
! sr
! r0 = temporary
! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
mov.l r2,@-sp
cli
mov.l $cpu_mode,r2
bld.b #6,@(0,r2) !previus SR.MD
bst.b #6,@(4*4,r15) !set cpu mode to SR.MD
bt 1f
! switch to kernel mode
bset.b #6,@(0,r2) !set SR.MD
mov.l $current_thread_info,r2
mov.l @r2,r2
mov #(THREAD_SIZE >> 8),r0
shll8 r0
add r2,r0 ! r0 = kernel stack tail
mov r15,r2 ! r2 = user stack top
mov r0,r15 ! switch kernel stack
mov.l r1,@-r15 ! TRA
sts.l macl, @-r15
sts.l mach, @-r15
stc.l gbr, @-r15
mov.l @(4*4,r2),r0
mov.l r0,@-r15 ! original SR
sts.l pr,@-r15
mov.l @(3*4,r2),r0
mov.l r0,@-r15 ! original PC
mov r2,r0
add #(3+2)*4,r0 ! rewind r0 - r3 + exception frame
lds r0,pr ! pr = original SP
movmu.l r3,@-r15 ! save regs
mov r2,r8 ! r8 = previus stack top
mov r1,r9 ! r9 = interrupt vector
! restore previous stack
mov.l @r8+,r2
mov.l @r8+,r0
mov.l @r8+,r1
bra 2f
movml.l r2,@-r15
1:
! in kernel exception
mov r15,r2
add #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
movmu.l r3,@-r15
mov r2,r8 ! r8 = previous stack top
mov r1,r9 ! r9 = interrupt vector
! restore exception frame & regs
mov.l @r8+,r2 ! old R2
mov.l @r8+,r0 ! old R0
mov.l @r8+,r1 ! old R1
mov.l @r8+,r10 ! old PC
mov.l @r8+,r11 ! old SR
movml.l r2,@-r15
mov.l r10,@(OFF_PC,r15)
mov.l r11,@(OFF_SR,r15)
mov.l r8,@(OFF_SP,r15) ! save old sp
mov r15,r8
add #OFF_TRA + 4,r8
mov.l r9,@-r8
sts.l macl,@-r8
sts.l mach,@-r8
stc.l gbr,@-r8
add #-4,r8
sts.l pr,@-r8
2:
! dispatch exception / interrupt
mov #64,r8
cmp/hs r8,r9
bt interrupt_entry ! vec >= 64 is interrupt
mov #31,r8
cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 31 is trap
mov.l 4f,r8
mov r9,r4
shll2 r9
add r9,r8
mov.l @r8,r8 ! exception handler address
tst r8,r8
bf 3f
mov.l 8f,r8 ! unhandled exception
3:
mov.l 5f,r10
jmp @r8
lds r10,pr
interrupt_entry:
mov r9,r4
mov r15,r5
mov.l 7f,r8
mov.l 6f,r9
jmp @r8
lds r9,pr
.align 2
4: .long exception_handling_table
5: .long ret_from_exception
6: .long ret_from_irq
7: .long do_IRQ
8: .long exception_error
trap_entry:
mov #0x30,r8
cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall
bt 1f
mov #0x1f,r9 ! convert to unified SH2/3/4 trap number
1:
shll2 r9 ! TRA
bra system_call ! jump common systemcall entry
mov r9,r8
#if defined(CONFIG_SH_STANDARD_BIOS)
/* Unwind the stack and jmp to the debug entry */
ENTRY(sh_bios_handler)
mov r15,r0
add #(22-4)*4-4,r0
ldc.l @r0+,gbr
lds.l @r0+,mach
lds.l @r0+,macl
mov r15,r0
mov.l @(OFF_SP,r0),r1
mov.l @(OFF_SR,r2),r3
mov.l r3,@-r1
mov.l @(OFF_SP,r2),r3
mov.l r3,@-r1
mov r15,r0
add #(22-4)*4-8,r0
mov.l 1f,r2
mov.l @r2,r2
stc sr,r3
mov.l r2,@r0
mov.l r3,@(4,r0)
mov.l r1,@(8,r0)
movml.l @r15+,r14
add #8,r15
lds.l @r15+, pr
mov.l @r15+,r15
rte
nop
.align 2
1: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
ENTRY(address_error_trap_handler)
mov r15,r4 ! regs
mov.l @(OFF_PC,r15),r6 ! pc
mov.l 1f,r0
jmp @r0
mov #0,r5 ! writeaccess is unknown
.align 2
1: .long do_address_error
restore_all:
stc sr,r0
or #0xf0,r0
ldc r0,sr ! all interrupt block (same BL = 1)
! restore special register
! overlap exception frame
mov r15,r0
add #17*4,r0
lds.l @r0+,pr
add #4,r0
ldc.l @r0+,gbr
lds.l @r0+,mach
lds.l @r0+,macl
mov r15,r0
mov.l $cpu_mode,r2
bld.b #6,@(OFF_SR,r15)
bst.b #6,@(0,r2) ! save CPU mode
mov.l @(OFF_SR,r0),r1
shll2 r1
shlr2 r1 ! clear MD bit
mov.l @(OFF_SP,r0),r2
add #-8,r2
mov.l r2,@(OFF_SP,r0) ! point exception frame top
mov.l r1,@(4,r2) ! set sr
mov.l @(OFF_PC,r0),r1
mov.l r1,@r2 ! set pc
get_current_thread_info r0, r1
mov.l $current_thread_info,r1
mov.l r0,@r1
movml.l @r15+,r14
mov.l @r15,r15
rte
nop
.align 2
$current_thread_info:
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
! common exception handler
#include "../../entry-common.S"
.data
! cpu operation mode
! bit30 = MD (compatible SH3/4)
__cpu_mode:
.long 0x40000000
.section .bss
__current_thread_info:
.long 0
ENTRY(exception_handling_table)
.space 4*32