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 exrl 0,0f 22 j . 230: br %r14 24 .endm 25 26/* 27 * int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode) 28 */ 29SYM_FUNC_START(_diag14_amode31) 30 lgr %r1,%r2 31 lgr %r2,%r3 32 lgr %r3,%r4 33 lhi %r5,-EIO 34 sam31 35 diag %r1,%r2,0x14 36.Ldiag14_ex: 37 ipm %r5 38 srl %r5,28 39.Ldiag14_fault: 40 sam64 41 lgfr %r2,%r5 42 BR_EX_AMODE31_r14 43 EX_TABLE_AMODE31(.Ldiag14_ex, .Ldiag14_fault) 44SYM_FUNC_END(_diag14_amode31) 45 46/* 47 * int _diag210_amode31(struct diag210 *addr) 48 */ 49SYM_FUNC_START(_diag210_amode31) 50 lgr %r1,%r2 51 lhi %r2,-1 52 sam31 53 diag %r1,%r0,0x210 54.Ldiag210_ex: 55 ipm %r2 56 srl %r2,28 57.Ldiag210_fault: 58 sam64 59 lgfr %r2,%r2 60 BR_EX_AMODE31_r14 61 EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault) 62SYM_FUNC_END(_diag210_amode31) 63 64/* 65 * int diag8c(struct diag8c *addr, struct ccw_dev_id *devno, size_t len) 66*/ 67SYM_FUNC_START(_diag8c_amode31) 68 llgf %r3,0(%r3) 69 sam31 70 diag %r2,%r4,0x8c 71.Ldiag8c_ex: 72 sam64 73 lgfr %r2,%r3 74 BR_EX_AMODE31_r14 75 EX_TABLE_AMODE31(.Ldiag8c_ex, .Ldiag8c_ex) 76SYM_FUNC_END(_diag8c_amode31) 77/* 78 * int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode) 79 */ 80SYM_FUNC_START(_diag26c_amode31) 81 lghi %r5,-EOPNOTSUPP 82 sam31 83 diag %r2,%r4,0x26c 84.Ldiag26c_ex: 85 sam64 86 lgfr %r2,%r5 87 BR_EX_AMODE31_r14 88 EX_TABLE_AMODE31(.Ldiag26c_ex, .Ldiag26c_ex) 89SYM_FUNC_END(_diag26c_amode31) 90 91/* 92 * void _diag0c_amode31(unsigned long rx) 93 */ 94SYM_FUNC_START(_diag0c_amode31) 95 sam31 96 diag %r2,%r2,0x0c 97 sam64 98 BR_EX_AMODE31_r14 99SYM_FUNC_END(_diag0c_amode31) 100 101/* 102 * void _diag308_reset_amode31(void) 103 * 104 * Calls diag 308 subcode 1 and continues execution 105 */ 106SYM_FUNC_START(_diag308_reset_amode31) 107 larl %r4,ctlregs # Save control registers 108 stctg %c0,%c15,0(%r4) 109 lg %r2,0(%r4) # Disable lowcore protection 110 nilh %r2,0xefff 111 larl %r4,ctlreg0 112 stg %r2,0(%r4) 113 lctlg %c0,%c0,0(%r4) 114 larl %r4,fpctl # Floating point control register 115 stfpc 0(%r4) 116 larl %r4,prefix # Save prefix register 117 stpx 0(%r4) 118 larl %r4,prefix_zero # Set prefix register to 0 119 spx 0(%r4) 120 larl %r4,continue_psw # Save PSW flags 121 epsw %r2,%r3 122 stm %r2,%r3,0(%r4) 123 larl %r4,.Lrestart_part2 # Setup restart PSW at absolute 0 124 larl %r3,restart_diag308_psw 125 og %r4,0(%r3) # Save PSW 126 lghi %r3,0 127 sturg %r4,%r3 # Use sturg, because of large pages 128 lghi %r1,1 129 lghi %r0,0 130 diag %r0,%r1,0x308 131.Lrestart_part2: 132 lhi %r0,0 # Load r0 with zero 133 lhi %r1,2 # Use mode 2 = ESAME (dump) 134 sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode 135 sam64 # Switch to 64 bit addressing mode 136 larl %r4,ctlregs # Restore control registers 137 lctlg %c0,%c15,0(%r4) 138 larl %r4,fpctl # Restore floating point ctl register 139 lfpc 0(%r4) 140 larl %r4,prefix # Restore prefix register 141 spx 0(%r4) 142 larl %r4,continue_psw # Restore PSW flags 143 larl %r2,.Lcontinue 144 stg %r2,8(%r4) 145 lpswe 0(%r4) 146.Lcontinue: 147 BR_EX_AMODE31_r14 148SYM_FUNC_END(_diag308_reset_amode31) 149 150 .section .amode31.data,"aw",@progbits 151 .balign 8 152SYM_DATA_LOCAL(restart_diag308_psw, .long 0x00080000,0x80000000) 153SYM_DATA_LOCAL(continue_psw, .quad 0,0) 154SYM_DATA_LOCAL(ctlreg0, .quad 0) 155SYM_DATA_LOCAL(ctlregs, .fill 16,8,0) 156SYM_DATA_LOCAL(fpctl, .long 0) 157SYM_DATA_LOCAL(prefix, .long 0) 158SYM_DATA_LOCAL(prefix_zero, .long 0) 159