18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Code that needs to run below 2 GB.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2019
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/linkage.h>
98c2ecf20Sopenharmony_ci#include <asm/errno.h>
108c2ecf20Sopenharmony_ci#include <asm/sigp.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci	.section .dma.text,"ax"
138c2ecf20Sopenharmony_ci/*
148c2ecf20Sopenharmony_ci * Simplified version of expoline thunk. The normal thunks can not be used here,
158c2ecf20Sopenharmony_ci * because they might be more than 2 GB away, and not reachable by the relative
168c2ecf20Sopenharmony_ci * branch. No comdat, exrl, etc. optimizations used here, because it only
178c2ecf20Sopenharmony_ci * affects a few functions that are not performance-relevant.
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ci	.macro BR_EX_DMA_r14
208c2ecf20Sopenharmony_ci	larl	%r1,0f
218c2ecf20Sopenharmony_ci	ex	0,0(%r1)
228c2ecf20Sopenharmony_ci	j	.
238c2ecf20Sopenharmony_ci0:	br	%r14
248c2ecf20Sopenharmony_ci	.endm
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * int _diag14_dma(unsigned long rx, unsigned long ry1, unsigned long subcode)
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_ciENTRY(_diag14_dma)
308c2ecf20Sopenharmony_ci	lgr	%r1,%r2
318c2ecf20Sopenharmony_ci	lgr	%r2,%r3
328c2ecf20Sopenharmony_ci	lgr	%r3,%r4
338c2ecf20Sopenharmony_ci	lhi	%r5,-EIO
348c2ecf20Sopenharmony_ci	sam31
358c2ecf20Sopenharmony_ci	diag	%r1,%r2,0x14
368c2ecf20Sopenharmony_ci.Ldiag14_ex:
378c2ecf20Sopenharmony_ci	ipm	%r5
388c2ecf20Sopenharmony_ci	srl	%r5,28
398c2ecf20Sopenharmony_ci.Ldiag14_fault:
408c2ecf20Sopenharmony_ci	sam64
418c2ecf20Sopenharmony_ci	lgfr	%r2,%r5
428c2ecf20Sopenharmony_ci	BR_EX_DMA_r14
438c2ecf20Sopenharmony_ci	EX_TABLE_DMA(.Ldiag14_ex, .Ldiag14_fault)
448c2ecf20Sopenharmony_ciENDPROC(_diag14_dma)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/*
478c2ecf20Sopenharmony_ci * int _diag210_dma(struct diag210 *addr)
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_ciENTRY(_diag210_dma)
508c2ecf20Sopenharmony_ci	lgr	%r1,%r2
518c2ecf20Sopenharmony_ci	lhi	%r2,-1
528c2ecf20Sopenharmony_ci	sam31
538c2ecf20Sopenharmony_ci	diag	%r1,%r0,0x210
548c2ecf20Sopenharmony_ci.Ldiag210_ex:
558c2ecf20Sopenharmony_ci	ipm	%r2
568c2ecf20Sopenharmony_ci	srl	%r2,28
578c2ecf20Sopenharmony_ci.Ldiag210_fault:
588c2ecf20Sopenharmony_ci	sam64
598c2ecf20Sopenharmony_ci	lgfr	%r2,%r2
608c2ecf20Sopenharmony_ci	BR_EX_DMA_r14
618c2ecf20Sopenharmony_ci	EX_TABLE_DMA(.Ldiag210_ex, .Ldiag210_fault)
628c2ecf20Sopenharmony_ciENDPROC(_diag210_dma)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/*
658c2ecf20Sopenharmony_ci * int _diag26c_dma(void *req, void *resp, enum diag26c_sc subcode)
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_ciENTRY(_diag26c_dma)
688c2ecf20Sopenharmony_ci	lghi	%r5,-EOPNOTSUPP
698c2ecf20Sopenharmony_ci	sam31
708c2ecf20Sopenharmony_ci	diag	%r2,%r4,0x26c
718c2ecf20Sopenharmony_ci.Ldiag26c_ex:
728c2ecf20Sopenharmony_ci	sam64
738c2ecf20Sopenharmony_ci	lgfr	%r2,%r5
748c2ecf20Sopenharmony_ci	BR_EX_DMA_r14
758c2ecf20Sopenharmony_ci	EX_TABLE_DMA(.Ldiag26c_ex, .Ldiag26c_ex)
768c2ecf20Sopenharmony_ciENDPROC(_diag26c_dma)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/*
798c2ecf20Sopenharmony_ci * void _diag0c_dma(struct hypfs_diag0c_entry *entry)
808c2ecf20Sopenharmony_ci */
818c2ecf20Sopenharmony_ciENTRY(_diag0c_dma)
828c2ecf20Sopenharmony_ci	sam31
838c2ecf20Sopenharmony_ci	diag	%r2,%r2,0x0c
848c2ecf20Sopenharmony_ci	sam64
858c2ecf20Sopenharmony_ci	BR_EX_DMA_r14
868c2ecf20Sopenharmony_ciENDPROC(_diag0c_dma)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/*
898c2ecf20Sopenharmony_ci * void _diag308_reset_dma(void)
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci * Calls diag 308 subcode 1 and continues execution
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_ciENTRY(_diag308_reset_dma)
948c2ecf20Sopenharmony_ci	larl	%r4,.Lctlregs		# Save control registers
958c2ecf20Sopenharmony_ci	stctg	%c0,%c15,0(%r4)
968c2ecf20Sopenharmony_ci	lg	%r2,0(%r4)		# Disable lowcore protection
978c2ecf20Sopenharmony_ci	nilh	%r2,0xefff
988c2ecf20Sopenharmony_ci	larl	%r4,.Lctlreg0
998c2ecf20Sopenharmony_ci	stg	%r2,0(%r4)
1008c2ecf20Sopenharmony_ci	lctlg	%c0,%c0,0(%r4)
1018c2ecf20Sopenharmony_ci	larl	%r4,.Lfpctl		# Floating point control register
1028c2ecf20Sopenharmony_ci	stfpc	0(%r4)
1038c2ecf20Sopenharmony_ci	larl	%r4,.Lprefix		# Save prefix register
1048c2ecf20Sopenharmony_ci	stpx	0(%r4)
1058c2ecf20Sopenharmony_ci	larl	%r4,.Lprefix_zero	# Set prefix register to 0
1068c2ecf20Sopenharmony_ci	spx	0(%r4)
1078c2ecf20Sopenharmony_ci	larl	%r4,.Lcontinue_psw	# Save PSW flags
1088c2ecf20Sopenharmony_ci	epsw	%r2,%r3
1098c2ecf20Sopenharmony_ci	stm	%r2,%r3,0(%r4)
1108c2ecf20Sopenharmony_ci	larl	%r4,restart_part2	# Setup restart PSW at absolute 0
1118c2ecf20Sopenharmony_ci	larl	%r3,.Lrestart_diag308_psw
1128c2ecf20Sopenharmony_ci	og	%r4,0(%r3)		# Save PSW
1138c2ecf20Sopenharmony_ci	lghi	%r3,0
1148c2ecf20Sopenharmony_ci	sturg	%r4,%r3			# Use sturg, because of large pages
1158c2ecf20Sopenharmony_ci	lghi	%r1,1
1168c2ecf20Sopenharmony_ci	lghi	%r0,0
1178c2ecf20Sopenharmony_ci	diag	%r0,%r1,0x308
1188c2ecf20Sopenharmony_cirestart_part2:
1198c2ecf20Sopenharmony_ci	lhi	%r0,0			# Load r0 with zero
1208c2ecf20Sopenharmony_ci	lhi	%r1,2			# Use mode 2 = ESAME (dump)
1218c2ecf20Sopenharmony_ci	sigp	%r1,%r0,SIGP_SET_ARCHITECTURE	# Switch to ESAME mode
1228c2ecf20Sopenharmony_ci	sam64				# Switch to 64 bit addressing mode
1238c2ecf20Sopenharmony_ci	larl	%r4,.Lctlregs		# Restore control registers
1248c2ecf20Sopenharmony_ci	lctlg	%c0,%c15,0(%r4)
1258c2ecf20Sopenharmony_ci	larl	%r4,.Lfpctl		# Restore floating point ctl register
1268c2ecf20Sopenharmony_ci	lfpc	0(%r4)
1278c2ecf20Sopenharmony_ci	larl	%r4,.Lprefix		# Restore prefix register
1288c2ecf20Sopenharmony_ci	spx	0(%r4)
1298c2ecf20Sopenharmony_ci	larl	%r4,.Lcontinue_psw	# Restore PSW flags
1308c2ecf20Sopenharmony_ci	lpswe	0(%r4)
1318c2ecf20Sopenharmony_ci.Lcontinue:
1328c2ecf20Sopenharmony_ci	BR_EX_DMA_r14
1338c2ecf20Sopenharmony_ciENDPROC(_diag308_reset_dma)
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	.section .dma.data,"aw",@progbits
1368c2ecf20Sopenharmony_ci.align	8
1378c2ecf20Sopenharmony_ci.Lrestart_diag308_psw:
1388c2ecf20Sopenharmony_ci	.long	0x00080000,0x80000000
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci.align 8
1418c2ecf20Sopenharmony_ci.Lcontinue_psw:
1428c2ecf20Sopenharmony_ci	.quad	0,.Lcontinue
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci.align 8
1458c2ecf20Sopenharmony_ci.Lctlreg0:
1468c2ecf20Sopenharmony_ci	.quad	0
1478c2ecf20Sopenharmony_ci.Lctlregs:
1488c2ecf20Sopenharmony_ci	.rept	16
1498c2ecf20Sopenharmony_ci	.quad	0
1508c2ecf20Sopenharmony_ci	.endr
1518c2ecf20Sopenharmony_ci.Lfpctl:
1528c2ecf20Sopenharmony_ci	.long	0
1538c2ecf20Sopenharmony_ci.Lprefix:
1548c2ecf20Sopenharmony_ci	.long	0
1558c2ecf20Sopenharmony_ci.Lprefix_zero:
1568c2ecf20Sopenharmony_ci	.long	0
157