xref: /kvm-unit-tests/s390x/macros.S (revision c9cda994b48d8e9bc0d001e0d3c5ed2c029a8687)
1865c4e50SJanosch Frank/* SPDX-License-Identifier: GPL-2.0-only */
2865c4e50SJanosch Frank/*
3865c4e50SJanosch Frank * s390x assembly macros
4865c4e50SJanosch Frank *
5865c4e50SJanosch Frank * Copyright (c) 2017 Red Hat Inc
636cfc0b7SJanosch Frank * Copyright (c) 2020, 2021 IBM Corp.
7865c4e50SJanosch Frank *
8865c4e50SJanosch Frank * Authors:
936cfc0b7SJanosch Frank *  Janosch Frank <frankja@linux.ibm.com>
10865c4e50SJanosch Frank *  Pierre Morel <pmorel@linux.ibm.com>
11865c4e50SJanosch Frank *  David Hildenbrand <david@redhat.com>
12865c4e50SJanosch Frank */
13865c4e50SJanosch Frank#include <asm/asm-offsets.h>
146adbca5eSJanosch Frank/*
156adbca5eSJanosch Frank * Exception handler macro that saves registers on the stack,
166adbca5eSJanosch Frank * allocates stack space and calls the C handler function. Afterwards
176adbca5eSJanosch Frank * we re-load the registers and load the old PSW.
186adbca5eSJanosch Frank */
196adbca5eSJanosch Frank	.macro CALL_INT_HANDLER c_func, old_psw
206adbca5eSJanosch Frank	SAVE_REGS_STACK
216adbca5eSJanosch Frank	/* Save the stack address in GR2 which is the first function argument */
226adbca5eSJanosch Frank	lgr     %r2, %r15
236adbca5eSJanosch Frank	/* Allocate stack space for called C function, as specified in s390 ELF ABI */
24*8e9fbb64SMarc Hartmayer	slgfi   %r15, STACK_FRAME_SIZE
251f4057ebSJanosch Frank	/*
261f4057ebSJanosch Frank	 * Save the address of the interrupt stack into the back chain
271f4057ebSJanosch Frank	 * of the called function.
281f4057ebSJanosch Frank	 */
291f4057ebSJanosch Frank	stg     %r2, STACK_FRAME_INT_BACKCHAIN(%r15)
306adbca5eSJanosch Frank	brasl	%r14, \c_func
31*8e9fbb64SMarc Hartmayer	algfi   %r15, STACK_FRAME_SIZE
326adbca5eSJanosch Frank	RESTORE_REGS_STACK
336adbca5eSJanosch Frank	lpswe	\old_psw
346adbca5eSJanosch Frank	.endm
356adbca5eSJanosch Frank
36865c4e50SJanosch Frank/* Save registers on the stack (r15), so we can have stacked interrupts. */
37865c4e50SJanosch Frank	.macro SAVE_REGS_STACK
3836cfc0b7SJanosch Frank	/* Allocate a full stack frame */
3936cfc0b7SJanosch Frank	slgfi   %r15, STACK_FRAME_INT_SIZE
40865c4e50SJanosch Frank	/* Store registers r0 to r14 on the stack */
4136cfc0b7SJanosch Frank	stmg    %r2, %r15, STACK_FRAME_INT_GRS0(%r15)
4236cfc0b7SJanosch Frank	stg     %r0, STACK_FRAME_INT_GRS1(%r15)
4336cfc0b7SJanosch Frank	stg     %r1, STACK_FRAME_INT_GRS1 + 8(%r15)
4436cfc0b7SJanosch Frank	/* Store the gr15 value before we allocated the new stack */
4536cfc0b7SJanosch Frank	lgr     %r0, %r15
4636cfc0b7SJanosch Frank	algfi   %r0, STACK_FRAME_INT_SIZE
4736cfc0b7SJanosch Frank	stg     %r0, 13 * 8 + STACK_FRAME_INT_GRS0(%r15)
4836cfc0b7SJanosch Frank	stg     %r0, STACK_FRAME_INT_BACKCHAIN(%r15)
4936cfc0b7SJanosch Frank	/*
5036cfc0b7SJanosch Frank	 * Store CR0 and load initial CR0 so AFP is active and we can
5136cfc0b7SJanosch Frank	 * access all fprs to save them.
5236cfc0b7SJanosch Frank	 */
5336cfc0b7SJanosch Frank	stctg   %c0,%c15,STACK_FRAME_INT_CRS(%r15)
5436cfc0b7SJanosch Frank	larl	%r1, initial_cr0
5536cfc0b7SJanosch Frank	lctlg	%c0, %c0, 0(%r1)
56865c4e50SJanosch Frank	/* Save fp register on stack: offset to SP is multiple of reg number */
57865c4e50SJanosch Frank	.irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
5836cfc0b7SJanosch Frank	std	\i, \i * 8 + STACK_FRAME_INT_FPRS(%r15)
59865c4e50SJanosch Frank	.endr
6036cfc0b7SJanosch Frank	/* Save fpc */
6136cfc0b7SJanosch Frank	stfpc	STACK_FRAME_INT_FPC(%r15)
62865c4e50SJanosch Frank	.endm
63865c4e50SJanosch Frank
64865c4e50SJanosch Frank/* Restore the register in reverse order */
65865c4e50SJanosch Frank	.macro RESTORE_REGS_STACK
66865c4e50SJanosch Frank	/* Restore fpc */
6736cfc0b7SJanosch Frank	lfpc	STACK_FRAME_INT_FPC(%r15)
68865c4e50SJanosch Frank	/* Restore fp register from stack: SP still where it was left */
69865c4e50SJanosch Frank	/* and offset to SP is a multiple of reg number */
70865c4e50SJanosch Frank	.irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
7136cfc0b7SJanosch Frank	ld	\i, \i * 8 + STACK_FRAME_INT_FPRS(%r15)
72865c4e50SJanosch Frank	.endr
7336cfc0b7SJanosch Frank	/* Load CR0 back */
7436cfc0b7SJanosch Frank	lctlg	%c0, %c15, STACK_FRAME_INT_CRS(%r15)
75865c4e50SJanosch Frank	/* Load the registers from stack */
7636cfc0b7SJanosch Frank	lg      %r0, STACK_FRAME_INT_GRS1(%r15)
7736cfc0b7SJanosch Frank	lg      %r1, STACK_FRAME_INT_GRS1 + 8(%r15)
7836cfc0b7SJanosch Frank	lmg     %r2, %r15, STACK_FRAME_INT_GRS0(%r15)
79865c4e50SJanosch Frank	.endm
80