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