1/* 2 * s390x startup code 3 * 4 * Copyright (c) 2017 Red Hat Inc 5 * 6 * Authors: 7 * Thomas Huth <thuth@redhat.com> 8 * David Hildenbrand <david@redhat.com> 9 * 10 * This code is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU Library General Public License version 2. 12 */ 13#include <asm/asm-offsets.h> 14#include <asm/sigp.h> 15 16.section .init 17 18/* 19 * Short init between 0x10000 and 0x10480 and then jump to 0x11000. 20 * 0x10480 - 0x11000 are written to by bootloader. 21 * 22 * For KVM and TCG kernel boot we are in 64 bit z/Arch mode. 23 * When booting from disk the initial short psw is in 31 bit mode. 24 * When running under LPAR or z/VM, we might start in 31 bit and esam mode. 25 */ 26 .globl start 27start: 28 /* Switch to z/Architecture mode and 64-bit */ 29 slr %r0, %r0 # Set cpuid to zero 30 lhi %r1, 2 # mode 2 = esame 31 sigp %r1, %r0, SIGP_SET_ARCHITECTURE 32 /* XOR all registers with themselves to clear them fully. */ 33 .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 34 xgr \i,\i 35 .endr 36 sam64 # Set addressing mode to 64 bit 37 /* setup stack */ 38 larl %r15, stackptr 39 /* setup initial PSW mask + control registers*/ 40 larl %r1, initial_psw 41 lpswe 0(%r1) 42clear_bss_start: 43 larl %r2, __bss_start 44 larl %r3, __bss_end 45 slgr %r3, %r2 # Get sizeof bss 46 aghi %r3,-1 47 srlg %r4,%r3,8 # Calc number of 256 byte chunks 48 ltgr %r4,%r4 49 lgr %r1,%r2 50 jz clear_bss_remainder # If none, clear remaining bytes 51clear_bss_loop: 52 xc 0(256,%r1), 0(%r1) # Clear 256 byte chunks via xor 53 la %r1, 256(%r1) 54 brctg %r4, clear_bss_loop 55clear_bss_remainder: 56 larl %r2, memsetxc 57 ex %r3, 0(%r2) 58 /* setup pgm interrupt handler */ 59 larl %r1, pgm_int_psw 60 mvc GEN_LC_PGM_NEW_PSW(16), 0(%r1) 61 /* setup ext interrupt handler */ 62 larl %r1, ext_int_psw 63 mvc GEN_LC_EXT_NEW_PSW(16), 0(%r1) 64 /* setup mcck interrupt handler */ 65 larl %r1, mcck_int_psw 66 mvc GEN_LC_MCCK_NEW_PSW(16), 0(%r1) 67 /* setup io interrupt handler */ 68 larl %r1, io_int_psw 69 mvc GEN_LC_IO_NEW_PSW(16), 0(%r1) 70 /* setup svc interrupt handler */ 71 larl %r1, svc_int_psw 72 mvc GEN_LC_SVC_NEW_PSW(16), 0(%r1) 73 /* setup cr0, enabling e.g. AFP-register control */ 74 larl %r1, initial_cr0 75 lctlg %c0, %c0, 0(%r1) 76 /* call setup() */ 77 brasl %r14, setup 78 /* forward test parameter */ 79 larl %r2, __argc 80 llgf %r2, 0(%r2) 81 larl %r3, __argv 82 /* call to main() */ 83 brasl %r14, main 84 /* forward exit code */ 85 lgr %r3, %r2 86 /* call exit() */ 87 j exit 88 89memsetxc: 90 xc 0(1,%r1),0(%r1) 91 92 .macro SAVE_REGS 93 /* save grs 0-15 */ 94 stmg %r0, %r15, GEN_LC_SW_INT_GRS 95 /* save crs 0-15 */ 96 stctg %c0, %c15, GEN_LC_SW_INT_CRS 97 /* load a cr0 that has the AFP control bit which enables all FPRs */ 98 larl %r1, initial_cr0 99 lctlg %c0, %c0, 0(%r1) 100 /* save fprs 0-15 + fpc */ 101 la %r1, GEN_LC_SW_INT_FPRS 102 .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 103 std \i, \i * 8(%r1) 104 .endr 105 stfpc GEN_LC_SW_INT_FPC 106 .endm 107 108 .macro RESTORE_REGS 109 /* restore fprs 0-15 + fpc */ 110 la %r1, GEN_LC_SW_INT_FPRS 111 .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 112 ld \i, \i * 8(%r1) 113 .endr 114 lfpc GEN_LC_SW_INT_FPC 115 /* restore crs 0-15 */ 116 lctlg %c0, %c15, GEN_LC_SW_INT_CRS 117 /* restore grs 0-15 */ 118 lmg %r0, %r15, GEN_LC_SW_INT_GRS 119 .endm 120 121.section .text 122/* 123 * load_reset calling convention: 124 * %r2 subcode (0 or 1) 125 */ 126.globl diag308_load_reset 127diag308_load_reset: 128 SAVE_REGS 129 /* Backup current PSW mask, as we have to restore it on success */ 130 epsw %r0, %r1 131 st %r0, GEN_LC_SW_INT_PSW 132 st %r1, GEN_LC_SW_INT_PSW + 4 133 /* Load reset psw mask (short psw, 64 bit) */ 134 lg %r0, reset_psw 135 /* Load the success label address */ 136 larl %r1, 0f 137 /* Or it to the mask */ 138 ogr %r0, %r1 139 /* Store it at the reset PSW location (real 0x0) */ 140 stg %r0, 0 141 /* Do the reset */ 142 diag %r0,%r2,0x308 143 /* Failure path */ 144 xgr %r2, %r2 145 br %r14 146 /* Success path */ 147 /* load a cr0 that has the AFP control bit which enables all FPRs */ 1480: larl %r1, initial_cr0 149 lctlg %c0, %c0, 0(%r1) 150 RESTORE_REGS 151 lhi %r2, 1 152 larl %r0, 1f 153 stg %r0, GEN_LC_SW_INT_PSW + 8 154 lpswe GEN_LC_SW_INT_PSW 1551: br %r14 156 157.globl smp_cpu_setup_state 158smp_cpu_setup_state: 159 xgr %r1, %r1 160 lmg %r0, %r15, GEN_LC_SW_INT_GRS 161 lctlg %c0, %c0, GEN_LC_SW_INT_CRS 162 /* We should only go once through cpu setup and not for every restart */ 163 stg %r14, GEN_LC_RESTART_NEW_PSW + 8 164 larl %r14, 0f 165 lpswe GEN_LC_SW_INT_PSW 166 /* If the function returns, just loop here */ 1670: j 0 168 169pgm_int: 170 SAVE_REGS 171 brasl %r14, handle_pgm_int 172 RESTORE_REGS 173 lpswe GEN_LC_PGM_OLD_PSW 174 175ext_int: 176 SAVE_REGS 177 brasl %r14, handle_ext_int 178 RESTORE_REGS 179 lpswe GEN_LC_EXT_OLD_PSW 180 181mcck_int: 182 SAVE_REGS 183 brasl %r14, handle_mcck_int 184 RESTORE_REGS 185 lpswe GEN_LC_MCCK_OLD_PSW 186 187io_int: 188 SAVE_REGS 189 brasl %r14, handle_io_int 190 RESTORE_REGS 191 lpswe GEN_LC_IO_OLD_PSW 192 193svc_int: 194 SAVE_REGS 195 brasl %r14, handle_svc_int 196 RESTORE_REGS 197 lpswe GEN_LC_SVC_OLD_PSW 198 199 .align 8 200reset_psw: 201 .quad 0x0008000180000000 202initial_psw: 203 .quad 0x0000000180000000, clear_bss_start 204pgm_int_psw: 205 .quad 0x0000000180000000, pgm_int 206ext_int_psw: 207 .quad 0x0000000180000000, ext_int 208mcck_int_psw: 209 .quad 0x0000000180000000, mcck_int 210io_int_psw: 211 .quad 0x0000000180000000, io_int 212svc_int_psw: 213 .quad 0x0000000180000000, svc_int 214initial_cr0: 215 /* enable AFP-register control, so FP regs (+BFP instr) can be used */ 216 .quad 0x0000000000040000 217