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/errno.h> 10#include <asm/sigp.h> 11 12 .section .dma.text,"ax" 13/* 14 * Simplified version of expoline thunk. The normal thunks can not be used here, 15 * because they might be more than 2 GB away, and not reachable by the relative 16 * branch. No comdat, exrl, etc. optimizations used here, because it only 17 * affects a few functions that are not performance-relevant. 18 */ 19 .macro BR_EX_DMA_r14 20 larl %r1,0f 21 ex 0,0(%r1) 22 j . 230: br %r14 24 .endm 25 26/* 27 * int _diag14_dma(unsigned long rx, unsigned long ry1, unsigned long subcode) 28 */ 29ENTRY(_diag14_dma) 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_DMA_r14 43 EX_TABLE_DMA(.Ldiag14_ex, .Ldiag14_fault) 44ENDPROC(_diag14_dma) 45 46/* 47 * int _diag210_dma(struct diag210 *addr) 48 */ 49ENTRY(_diag210_dma) 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_DMA_r14 61 EX_TABLE_DMA(.Ldiag210_ex, .Ldiag210_fault) 62ENDPROC(_diag210_dma) 63 64/* 65 * int _diag26c_dma(void *req, void *resp, enum diag26c_sc subcode) 66 */ 67ENTRY(_diag26c_dma) 68 lghi %r5,-EOPNOTSUPP 69 sam31 70 diag %r2,%r4,0x26c 71.Ldiag26c_ex: 72 sam64 73 lgfr %r2,%r5 74 BR_EX_DMA_r14 75 EX_TABLE_DMA(.Ldiag26c_ex, .Ldiag26c_ex) 76ENDPROC(_diag26c_dma) 77 78/* 79 * void _diag0c_dma(struct hypfs_diag0c_entry *entry) 80 */ 81ENTRY(_diag0c_dma) 82 sam31 83 diag %r2,%r2,0x0c 84 sam64 85 BR_EX_DMA_r14 86ENDPROC(_diag0c_dma) 87 88/* 89 * void _diag308_reset_dma(void) 90 * 91 * Calls diag 308 subcode 1 and continues execution 92 */ 93ENTRY(_diag308_reset_dma) 94 larl %r4,.Lctlregs # Save control registers 95 stctg %c0,%c15,0(%r4) 96 lg %r2,0(%r4) # Disable lowcore protection 97 nilh %r2,0xefff 98 larl %r4,.Lctlreg0 99 stg %r2,0(%r4) 100 lctlg %c0,%c0,0(%r4) 101 larl %r4,.Lfpctl # Floating point control register 102 stfpc 0(%r4) 103 larl %r4,.Lprefix # Save prefix register 104 stpx 0(%r4) 105 larl %r4,.Lprefix_zero # Set prefix register to 0 106 spx 0(%r4) 107 larl %r4,.Lcontinue_psw # Save PSW flags 108 epsw %r2,%r3 109 stm %r2,%r3,0(%r4) 110 larl %r4,restart_part2 # Setup restart PSW at absolute 0 111 larl %r3,.Lrestart_diag308_psw 112 og %r4,0(%r3) # Save PSW 113 lghi %r3,0 114 sturg %r4,%r3 # Use sturg, because of large pages 115 lghi %r1,1 116 lghi %r0,0 117 diag %r0,%r1,0x308 118restart_part2: 119 lhi %r0,0 # Load r0 with zero 120 lhi %r1,2 # Use mode 2 = ESAME (dump) 121 sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode 122 sam64 # Switch to 64 bit addressing mode 123 larl %r4,.Lctlregs # Restore control registers 124 lctlg %c0,%c15,0(%r4) 125 larl %r4,.Lfpctl # Restore floating point ctl register 126 lfpc 0(%r4) 127 larl %r4,.Lprefix # Restore prefix register 128 spx 0(%r4) 129 larl %r4,.Lcontinue_psw # Restore PSW flags 130 lpswe 0(%r4) 131.Lcontinue: 132 BR_EX_DMA_r14 133ENDPROC(_diag308_reset_dma) 134 135 .section .dma.data,"aw",@progbits 136.align 8 137.Lrestart_diag308_psw: 138 .long 0x00080000,0x80000000 139 140.align 8 141.Lcontinue_psw: 142 .quad 0,.Lcontinue 143 144.align 8 145.Lctlreg0: 146 .quad 0 147.Lctlregs: 148 .rept 16 149 .quad 0 150 .endr 151.Lfpctl: 152 .long 0 153.Lprefix: 154 .long 0 155.Lprefix_zero: 156 .long 0 157