| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * s390x assembly library |
| * |
| * Copyright (c) 2019 IBM Corp. |
| * |
| * Authors: |
| * Janosch Frank <frankja@linux.ibm.com> |
| */ |
| #include <asm/asm-offsets.h> |
| #include <asm/sigp.h> |
| |
| #include "macros.S" |
| |
| /* |
| * load_reset calling convention: |
| * %r2 subcode (0 or 1) |
| */ |
| .globl diag308_load_reset |
| diag308_load_reset: |
| SAVE_REGS_STACK |
| /* Backup current PSW mask, as we have to restore it on success */ |
| epsw %r0, %r1 |
| st %r0, GEN_LC_SW_INT_PSW |
| st %r1, GEN_LC_SW_INT_PSW + 4 |
| /* Load reset psw mask (short psw, 64 bit) */ |
| lg %r0, reset_psw |
| /* Load the success label address */ |
| larl %r1, 0f |
| /* Or it to the mask */ |
| ogr %r0, %r1 |
| /* Store it at the reset PSW location (real 0x0) */ |
| stg %r0, 0 |
| stg %r15, GEN_LC_SW_INT_GRS + 15 * 8 |
| /* Do the reset */ |
| diag %r0,%r2,0x308 |
| /* Failure path */ |
| xgr %r2, %r2 |
| br %r14 |
| /* Success path */ |
| /* load a cr0 that has the AFP control bit which enables all FPRs */ |
| 0: larl %r1, initial_cr0 |
| lctlg %c0, %c0, 0(%r1) |
| lg %r15, GEN_LC_SW_INT_GRS + 15 * 8 |
| RESTORE_REGS_STACK |
| lhi %r2, 1 |
| larl %r0, 1f |
| stg %r0, GEN_LC_SW_INT_PSW + 8 |
| lpswe GEN_LC_SW_INT_PSW |
| 1: br %r14 |
| |
| /* Sets up general registers and cr0 when a new cpu is brought online. */ |
| .globl smp_cpu_setup_state |
| smp_cpu_setup_state: |
| xgr %r1, %r1 |
| lmg %r0, %r15, GEN_LC_SW_INT_GRS |
| lctlg %c0, %c0, GEN_LC_SW_INT_CRS |
| /* We should only go once through cpu setup and not for every restart */ |
| stg %r14, GEN_LC_RESTART_NEW_PSW + 8 |
| larl %r14, 0f |
| lpswe GEN_LC_SW_INT_PSW |
| /* If the function returns, just loop here */ |
| 0: j 0 |
| |
| /* |
| * sie64a calling convention: |
| * %r2 pointer to sie control block |
| * %r3 guest register save area |
| */ |
| .globl sie64a |
| sie64a: |
| # Save host grs, fprs, fpc |
| stmg %r0,%r14,SIE_SAVEAREA_HOST_GRS(%r3) # save kernel registers |
| .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
| std \i, \i * 8 + SIE_SAVEAREA_HOST_FPRS(%r3) |
| .endr |
| stfpc SIE_SAVEAREA_HOST_FPC(%r3) |
| |
| stctg %c1, %c1, SIE_SAVEAREA_HOST_ASCE(%r3) |
| lctlg %c1, %c1, SIE_SAVEAREA_GUEST_ASCE(%r3) |
| |
| # Store scb and save_area pointer into stack frame |
| stg %r2,__SF_SIE_CONTROL(%r15) # save control block pointer |
| stg %r3,__SF_SIE_SAVEAREA(%r15) # save guest register save area |
| .globl sie_entry_gregs |
| sie_entry_gregs: |
| # Load guest's gprs, fprs and fpc |
| .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
| ld \i, \i * 8 + SIE_SAVEAREA_GUEST_FPRS(%r3) |
| .endr |
| lfpc SIE_SAVEAREA_GUEST_FPC(%r3) |
| lmg %r0,%r13,SIE_SAVEAREA_GUEST_GRS(%r3) |
| |
| # Move scb ptr into r14 for the sie instruction |
| lg %r14,__SF_SIE_CONTROL(%r15) |
| |
| .globl sie_entry |
| sie_entry: |
| sie 0(%r14) |
| nopr 7 |
| nopr 7 |
| nopr 7 |
| |
| .globl sie_exit |
| sie_exit: |
| # Load guest register save area |
| lg %r14,__SF_SIE_SAVEAREA(%r15) |
| |
| # Restore the host asce |
| lctlg %c1, %c1, SIE_SAVEAREA_HOST_ASCE(%r14) |
| |
| # Store guest's gprs, fprs and fpc |
| stmg %r0,%r13,SIE_SAVEAREA_GUEST_GRS(%r14) # save guest gprs 0-13 |
| .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
| std \i, \i * 8 + SIE_SAVEAREA_GUEST_FPRS(%r14) |
| .endr |
| stfpc SIE_SAVEAREA_GUEST_FPC(%r14) |
| |
| # Restore host's gprs, fprs and fpc |
| .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
| ld \i, \i * 8 + SIE_SAVEAREA_HOST_FPRS(%r14) |
| .endr |
| lfpc SIE_SAVEAREA_HOST_FPC(%r14) |
| lmg %r0,%r14,SIE_SAVEAREA_HOST_GRS(%r14) # restore kernel registers |
| .globl sie_exit_gregs |
| sie_exit_gregs: |
| br %r14 |
| |
| .align 8 |
| reset_psw: |
| .quad 0x0008000180000000 |