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

source code of linux/arch/s390/kernel/text_amode31.S