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