1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Code that needs to run below 2 GB. 4 * 5 * Copyright IBM Corp. 2019 6 */ 7 8#include <linux/linkage.h> 9#include <asm/asm-extable.h> 10#include <asm/errno.h> 11#include <asm/sigp.h> 12 13 .section .amode31.text,"ax" 14/* 15 * Simplified version of expoline thunk. The normal thunks can not be used here, 16 * because they might be more than 2 GB away, and not reachable by the relative 17 * branch. No comdat, exrl, etc. optimizations used here, because it only 18 * affects a few functions that are not performance-relevant. 19 */ 20 .macro BR_EX_AMODE31_r14 21 larl %r1,0f 22 ex 0,0(%r1) 23 j . 240: br %r14 25 .endm 26 27/* 28 * int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode) 29 */ 30SYM_FUNC_START(_diag14_amode31) 31 lgr %r1,%r2 32 lgr %r2,%r3 33 lgr %r3,%r4 34 lhi %r5,-EIO 35 sam31 36 diag %r1,%r2,0x14 37.Ldiag14_ex: 38 ipm %r5 39 srl %r5,28 40.Ldiag14_fault: 41 sam64 42 lgfr %r2,%r5 43 BR_EX_AMODE31_r14 44 EX_TABLE_AMODE31(.Ldiag14_ex, .Ldiag14_fault) 45SYM_FUNC_END(_diag14_amode31) 46 47/* 48 * int _diag210_amode31(struct diag210 *addr) 49 */ 50SYM_FUNC_START(_diag210_amode31) 51 lgr %r1,%r2 52 lhi %r2,-1 53 sam31 54 diag %r1,%r0,0x210 55.Ldiag210_ex: 56 ipm %r2 57 srl %r2,28 58.Ldiag210_fault: 59 sam64 60 lgfr %r2,%r2 61 BR_EX_AMODE31_r14 62 EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault) 63SYM_FUNC_END(_diag210_amode31) 64 65/* 66 * int diag8c(struct diag8c *addr, struct ccw_dev_id *devno, size_t len) 67*/ 68SYM_FUNC_START(_diag8c_amode31) 69 llgf %r3,0(%r3) 70 sam31 71 diag %r2,%r4,0x8c 72.Ldiag8c_ex: 73 sam64 74 lgfr %r2,%r3 75 BR_EX_AMODE31_r14 76 EX_TABLE_AMODE31(.Ldiag8c_ex, .Ldiag8c_ex) 77SYM_FUNC_END(_diag8c_amode31) 78/* 79 * int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode) 80 */ 81SYM_FUNC_START(_diag26c_amode31) 82 lghi %r5,-EOPNOTSUPP 83 sam31 84 diag %r2,%r4,0x26c 85.Ldiag26c_ex: 86 sam64 87 lgfr %r2,%r5 88 BR_EX_AMODE31_r14 89 EX_TABLE_AMODE31(.Ldiag26c_ex, .Ldiag26c_ex) 90SYM_FUNC_END(_diag26c_amode31) 91 92/* 93 * void _diag0c_amode31(unsigned long rx) 94 */ 95SYM_FUNC_START(_diag0c_amode31) 96 sam31 97 diag %r2,%r2,0x0c 98 sam64 99 BR_EX_AMODE31_r14 100SYM_FUNC_END(_diag0c_amode31) 101 102/* 103 * void _diag308_reset_amode31(void) 104 * 105 * Calls diag 308 subcode 1 and continues execution 106 */ 107SYM_FUNC_START(_diag308_reset_amode31) 108 larl %r4,ctlregs # Save control registers 109 stctg %c0,%c15,0(%r4) 110 lg %r2,0(%r4) # Disable lowcore protection 111 nilh %r2,0xefff 112 larl %r4,ctlreg0 113 stg %r2,0(%r4) 114 lctlg %c0,%c0,0(%r4) 115 larl %r4,fpctl # Floating point control register 116 stfpc 0(%r4) 117 larl %r4,prefix # Save prefix register 118 stpx 0(%r4) 119 larl %r4,prefix_zero # Set prefix register to 0 120 spx 0(%r4) 121 larl %r4,continue_psw # Save PSW flags 122 epsw %r2,%r3 123 stm %r2,%r3,0(%r4) 124 larl %r4,.Lrestart_part2 # Setup restart PSW at absolute 0 125 larl %r3,restart_diag308_psw 126 og %r4,0(%r3) # Save PSW 127 lghi %r3,0 128 sturg %r4,%r3 # Use sturg, because of large pages 129 lghi %r1,1 130 lghi %r0,0 131 diag %r0,%r1,0x308 132.Lrestart_part2: 133 lhi %r0,0 # Load r0 with zero 134 lhi %r1,2 # Use mode 2 = ESAME (dump) 135 sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode 136 sam64 # Switch to 64 bit addressing mode 137 larl %r4,ctlregs # Restore control registers 138 lctlg %c0,%c15,0(%r4) 139 larl %r4,fpctl # Restore floating point ctl register 140 lfpc 0(%r4) 141 larl %r4,prefix # Restore prefix register 142 spx 0(%r4) 143 larl %r4,continue_psw # Restore PSW flags 144 larl %r2,.Lcontinue 145 stg %r2,8(%r4) 146 lpswe 0(%r4) 147.Lcontinue: 148 BR_EX_AMODE31_r14 149SYM_FUNC_END(_diag308_reset_amode31) 150 151 .section .amode31.data,"aw",@progbits 152 .balign 8 153SYM_DATA_LOCAL(restart_diag308_psw, .long 0x00080000,0x80000000) 154SYM_DATA_LOCAL(continue_psw, .quad 0,0) 155SYM_DATA_LOCAL(ctlreg0, .quad 0) 156SYM_DATA_LOCAL(ctlregs, .fill 16,8,0) 157SYM_DATA_LOCAL(fpctl, .long 0) 158SYM_DATA_LOCAL(prefix, .long 0) 159SYM_DATA_LOCAL(prefix_zero, .long 0) 160