mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

exrl is present in all machines currently supported, therefore prefer it over ex. This saves one instruction and doesn't need an additional register to hold the address of the target instruction. Signed-off-by: Sven Schnelle <svens@linux.ibm.com> Reviewed-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
158 lines
3.6 KiB
ArmAsm
158 lines
3.6 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Code that needs to run below 2 GB.
|
|
*
|
|
* Copyright IBM Corp. 2019
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/asm-extable.h>
|
|
#include <asm/errno.h>
|
|
#include <asm/sigp.h>
|
|
|
|
.section .amode31.text,"ax"
|
|
/*
|
|
* Simplified version of expoline thunk. The normal thunks can not be used here,
|
|
* because they might be more than 2 GB away, and not reachable by the relative
|
|
* branch. No comdat, exrl, etc. optimizations used here, because it only
|
|
* affects a few functions that are not performance-relevant.
|
|
*/
|
|
.macro BR_EX_AMODE31_r14
|
|
exrl 0,0f
|
|
j .
|
|
0: br %r14
|
|
.endm
|
|
|
|
/*
|
|
* int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode)
|
|
*/
|
|
SYM_FUNC_START(_diag14_amode31)
|
|
lgr %r1,%r2
|
|
lgr %r2,%r3
|
|
lgr %r3,%r4
|
|
lhi %r5,-EIO
|
|
sam31
|
|
diag %r1,%r2,0x14
|
|
.Ldiag14_ex:
|
|
ipm %r5
|
|
srl %r5,28
|
|
.Ldiag14_fault:
|
|
sam64
|
|
lgfr %r2,%r5
|
|
BR_EX_AMODE31_r14
|
|
EX_TABLE_AMODE31(.Ldiag14_ex, .Ldiag14_fault)
|
|
SYM_FUNC_END(_diag14_amode31)
|
|
|
|
/*
|
|
* int _diag210_amode31(struct diag210 *addr)
|
|
*/
|
|
SYM_FUNC_START(_diag210_amode31)
|
|
lgr %r1,%r2
|
|
lhi %r2,-1
|
|
sam31
|
|
diag %r1,%r0,0x210
|
|
.Ldiag210_ex:
|
|
ipm %r2
|
|
srl %r2,28
|
|
.Ldiag210_fault:
|
|
sam64
|
|
lgfr %r2,%r2
|
|
BR_EX_AMODE31_r14
|
|
EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault)
|
|
SYM_FUNC_END(_diag210_amode31)
|
|
|
|
/*
|
|
* int diag8c(struct diag8c *addr, struct ccw_dev_id *devno, size_t len)
|
|
*/
|
|
SYM_FUNC_START(_diag8c_amode31)
|
|
llgf %r3,0(%r3)
|
|
sam31
|
|
diag %r2,%r4,0x8c
|
|
.Ldiag8c_ex:
|
|
sam64
|
|
lgfr %r2,%r3
|
|
BR_EX_AMODE31_r14
|
|
EX_TABLE_AMODE31(.Ldiag8c_ex, .Ldiag8c_ex)
|
|
SYM_FUNC_END(_diag8c_amode31)
|
|
/*
|
|
* int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode)
|
|
*/
|
|
SYM_FUNC_START(_diag26c_amode31)
|
|
lghi %r5,-EOPNOTSUPP
|
|
sam31
|
|
diag %r2,%r4,0x26c
|
|
.Ldiag26c_ex:
|
|
sam64
|
|
lgfr %r2,%r5
|
|
BR_EX_AMODE31_r14
|
|
EX_TABLE_AMODE31(.Ldiag26c_ex, .Ldiag26c_ex)
|
|
SYM_FUNC_END(_diag26c_amode31)
|
|
|
|
/*
|
|
* void _diag0c_amode31(unsigned long rx)
|
|
*/
|
|
SYM_FUNC_START(_diag0c_amode31)
|
|
sam31
|
|
diag %r2,%r2,0x0c
|
|
sam64
|
|
BR_EX_AMODE31_r14
|
|
SYM_FUNC_END(_diag0c_amode31)
|
|
|
|
/*
|
|
* void _diag308_reset_amode31(void)
|
|
*
|
|
* Calls diag 308 subcode 1 and continues execution
|
|
*/
|
|
SYM_FUNC_START(_diag308_reset_amode31)
|
|
larl %r4,ctlregs # Save control registers
|
|
stctg %c0,%c15,0(%r4)
|
|
lg %r2,0(%r4) # Disable lowcore protection
|
|
nilh %r2,0xefff
|
|
larl %r4,ctlreg0
|
|
stg %r2,0(%r4)
|
|
lctlg %c0,%c0,0(%r4)
|
|
larl %r4,fpctl # Floating point control register
|
|
stfpc 0(%r4)
|
|
larl %r4,prefix # Save prefix register
|
|
stpx 0(%r4)
|
|
larl %r4,prefix_zero # Set prefix register to 0
|
|
spx 0(%r4)
|
|
larl %r4,continue_psw # Save PSW flags
|
|
epsw %r2,%r3
|
|
stm %r2,%r3,0(%r4)
|
|
larl %r4,.Lrestart_part2 # Setup restart PSW at absolute 0
|
|
larl %r3,restart_diag308_psw
|
|
og %r4,0(%r3) # Save PSW
|
|
lghi %r3,0
|
|
sturg %r4,%r3 # Use sturg, because of large pages
|
|
lghi %r1,1
|
|
lghi %r0,0
|
|
diag %r0,%r1,0x308
|
|
.Lrestart_part2:
|
|
lhi %r0,0 # Load r0 with zero
|
|
lhi %r1,2 # Use mode 2 = ESAME (dump)
|
|
sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode
|
|
sam64 # Switch to 64 bit addressing mode
|
|
larl %r4,ctlregs # Restore control registers
|
|
lctlg %c0,%c15,0(%r4)
|
|
larl %r4,fpctl # Restore floating point ctl register
|
|
lfpc 0(%r4)
|
|
larl %r4,prefix # Restore prefix register
|
|
spx 0(%r4)
|
|
larl %r4,continue_psw # Restore PSW flags
|
|
larl %r2,.Lcontinue
|
|
stg %r2,8(%r4)
|
|
lpswe 0(%r4)
|
|
.Lcontinue:
|
|
BR_EX_AMODE31_r14
|
|
SYM_FUNC_END(_diag308_reset_amode31)
|
|
|
|
.section .amode31.data,"aw",@progbits
|
|
.balign 8
|
|
SYM_DATA_LOCAL(restart_diag308_psw, .long 0x00080000,0x80000000)
|
|
SYM_DATA_LOCAL(continue_psw, .quad 0,0)
|
|
SYM_DATA_LOCAL(ctlreg0, .quad 0)
|
|
SYM_DATA_LOCAL(ctlregs, .fill 16,8,0)
|
|
SYM_DATA_LOCAL(fpctl, .long 0)
|
|
SYM_DATA_LOCAL(prefix, .long 0)
|
|
SYM_DATA_LOCAL(prefix_zero, .long 0)
|