GNU Linux-libre 6.1.90-gnu
[releases.git] / arch / s390 / kernel / text_amode31.S
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       .
24 0:      br      %r14
25         .endm
26
27 /*
28  * int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode)
29  */
30 ENTRY(_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)
45 ENDPROC(_diag14_amode31)
46
47 /*
48  * int _diag210_amode31(struct diag210 *addr)
49  */
50 ENTRY(_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)
63 ENDPROC(_diag210_amode31)
64
65 /*
66  * int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode)
67  */
68 ENTRY(_diag26c_amode31)
69         lghi    %r5,-EOPNOTSUPP
70         sam31
71         diag    %r2,%r4,0x26c
72 .Ldiag26c_ex:
73         sam64
74         lgfr    %r2,%r5
75         BR_EX_AMODE31_r14
76         EX_TABLE_AMODE31(.Ldiag26c_ex, .Ldiag26c_ex)
77 ENDPROC(_diag26c_amode31)
78
79 /*
80  * void _diag0c_amode31(struct hypfs_diag0c_entry *entry)
81  */
82 ENTRY(_diag0c_amode31)
83         sam31
84         diag    %r2,%r2,0x0c
85         sam64
86         BR_EX_AMODE31_r14
87 ENDPROC(_diag0c_amode31)
88
89 /*
90  * void _diag308_reset_amode31(void)
91  *
92  * Calls diag 308 subcode 1 and continues execution
93  */
94 ENTRY(_diag308_reset_amode31)
95         larl    %r4,.Lctlregs           # Save control registers
96         stctg   %c0,%c15,0(%r4)
97         lg      %r2,0(%r4)              # Disable lowcore protection
98         nilh    %r2,0xefff
99         larl    %r4,.Lctlreg0
100         stg     %r2,0(%r4)
101         lctlg   %c0,%c0,0(%r4)
102         larl    %r4,.Lfpctl             # Floating point control register
103         stfpc   0(%r4)
104         larl    %r4,.Lprefix            # Save prefix register
105         stpx    0(%r4)
106         larl    %r4,.Lprefix_zero       # Set prefix register to 0
107         spx     0(%r4)
108         larl    %r4,.Lcontinue_psw      # Save PSW flags
109         epsw    %r2,%r3
110         stm     %r2,%r3,0(%r4)
111         larl    %r4,.Lrestart_part2     # Setup restart PSW at absolute 0
112         larl    %r3,.Lrestart_diag308_psw
113         og      %r4,0(%r3)              # Save PSW
114         lghi    %r3,0
115         sturg   %r4,%r3                 # Use sturg, because of large pages
116         lghi    %r1,1
117         lghi    %r0,0
118         diag    %r0,%r1,0x308
119 .Lrestart_part2:
120         lhi     %r0,0                   # Load r0 with zero
121         lhi     %r1,2                   # Use mode 2 = ESAME (dump)
122         sigp    %r1,%r0,SIGP_SET_ARCHITECTURE   # Switch to ESAME mode
123         sam64                           # Switch to 64 bit addressing mode
124         larl    %r4,.Lctlregs           # Restore control registers
125         lctlg   %c0,%c15,0(%r4)
126         larl    %r4,.Lfpctl             # Restore floating point ctl register
127         lfpc    0(%r4)
128         larl    %r4,.Lprefix            # Restore prefix register
129         spx     0(%r4)
130         larl    %r4,.Lcontinue_psw      # Restore PSW flags
131         larl    %r2,.Lcontinue
132         stg     %r2,8(%r4)
133         lpswe   0(%r4)
134 .Lcontinue:
135         BR_EX_AMODE31_r14
136 ENDPROC(_diag308_reset_amode31)
137
138         .section .amode31.data,"aw",@progbits
139 .align  8
140 .Lrestart_diag308_psw:
141         .long   0x00080000,0x80000000
142
143 .align 8
144 .Lcontinue_psw:
145         .quad   0,0
146
147 .align 8
148 .Lctlreg0:
149         .quad   0
150 .Lctlregs:
151         .rept   16
152         .quad   0
153         .endr
154 .Lfpctl:
155         .long   0
156 .Lprefix:
157         .long   0
158 .Lprefix_zero:
159         .long   0