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