s390/boot: fix use of expolines in the DMA code
[linux-2.6-block.git] / arch / s390 / boot / text_dma.S
CommitLineData
a80313ff
GS
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
463f36c7
AE
20 larl %r1,0f
21 ex 0,0(%r1)
22 j .
230: br %r14
a80313ff
GS
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)
26a374ae 44ENDPROC(_diag14_dma)
a80313ff
GS
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)
26a374ae 62ENDPROC(_diag210_dma)
a80313ff
GS
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)
26a374ae 76ENDPROC(_diag26c_dma)
a80313ff
GS
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
26a374ae 86ENDPROC(_diag0c_dma)
a80313ff 87
a80313ff
GS
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
26a374ae 133ENDPROC(_diag308_reset_dma)
a80313ff
GS
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