xref: /kvm-unit-tests/s390x/macros.S (revision c9cda994b48d8e9bc0d001e0d3c5ed2c029a8687)
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * s390x assembly macros
4 *
5 * Copyright (c) 2017 Red Hat Inc
6 * Copyright (c) 2020, 2021 IBM Corp.
7 *
8 * Authors:
9 *  Janosch Frank <frankja@linux.ibm.com>
10 *  Pierre Morel <pmorel@linux.ibm.com>
11 *  David Hildenbrand <david@redhat.com>
12 */
13#include <asm/asm-offsets.h>
14/*
15 * Exception handler macro that saves registers on the stack,
16 * allocates stack space and calls the C handler function. Afterwards
17 * we re-load the registers and load the old PSW.
18 */
19	.macro CALL_INT_HANDLER c_func, old_psw
20	SAVE_REGS_STACK
21	/* Save the stack address in GR2 which is the first function argument */
22	lgr     %r2, %r15
23	/* Allocate stack space for called C function, as specified in s390 ELF ABI */
24	slgfi   %r15, STACK_FRAME_SIZE
25	/*
26	 * Save the address of the interrupt stack into the back chain
27	 * of the called function.
28	 */
29	stg     %r2, STACK_FRAME_INT_BACKCHAIN(%r15)
30	brasl	%r14, \c_func
31	algfi   %r15, STACK_FRAME_SIZE
32	RESTORE_REGS_STACK
33	lpswe	\old_psw
34	.endm
35
36/* Save registers on the stack (r15), so we can have stacked interrupts. */
37	.macro SAVE_REGS_STACK
38	/* Allocate a full stack frame */
39	slgfi   %r15, STACK_FRAME_INT_SIZE
40	/* Store registers r0 to r14 on the stack */
41	stmg    %r2, %r15, STACK_FRAME_INT_GRS0(%r15)
42	stg     %r0, STACK_FRAME_INT_GRS1(%r15)
43	stg     %r1, STACK_FRAME_INT_GRS1 + 8(%r15)
44	/* Store the gr15 value before we allocated the new stack */
45	lgr     %r0, %r15
46	algfi   %r0, STACK_FRAME_INT_SIZE
47	stg     %r0, 13 * 8 + STACK_FRAME_INT_GRS0(%r15)
48	stg     %r0, STACK_FRAME_INT_BACKCHAIN(%r15)
49	/*
50	 * Store CR0 and load initial CR0 so AFP is active and we can
51	 * access all fprs to save them.
52	 */
53	stctg   %c0,%c15,STACK_FRAME_INT_CRS(%r15)
54	larl	%r1, initial_cr0
55	lctlg	%c0, %c0, 0(%r1)
56	/* Save fp register on stack: offset to SP is multiple of reg number */
57	.irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
58	std	\i, \i * 8 + STACK_FRAME_INT_FPRS(%r15)
59	.endr
60	/* Save fpc */
61	stfpc	STACK_FRAME_INT_FPC(%r15)
62	.endm
63
64/* Restore the register in reverse order */
65	.macro RESTORE_REGS_STACK
66	/* Restore fpc */
67	lfpc	STACK_FRAME_INT_FPC(%r15)
68	/* Restore fp register from stack: SP still where it was left */
69	/* and offset to SP is a multiple of reg number */
70	.irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
71	ld	\i, \i * 8 + STACK_FRAME_INT_FPRS(%r15)
72	.endr
73	/* Load CR0 back */
74	lctlg	%c0, %c15, STACK_FRAME_INT_CRS(%r15)
75	/* Load the registers from stack */
76	lg      %r0, STACK_FRAME_INT_GRS1(%r15)
77	lg      %r1, STACK_FRAME_INT_GRS1 + 8(%r15)
78	lmg     %r2, %r15, STACK_FRAME_INT_GRS0(%r15)
79	.endm
80