1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * HPMC (High Priority Machine Check) handler. 4 * 5 * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org> 6 * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) 7 * Copyright (C) 2000 Hewlett-Packard (John Marvin) 8 */ 9 10 11 /* 12 * This HPMC handler retrieves the HPMC pim data, resets IO and 13 * returns to the default trap handler with code set to 1 (HPMC). 14 * The default trap handler calls handle interruption, which 15 * does a stack and register dump. This at least allows kernel 16 * developers to get back to C code in virtual mode, where they 17 * have the option to examine and print values from memory that 18 * would help in debugging an HPMC caused by a software bug. 19 * 20 * There is more to do here: 21 * 22 * 1) On MP systems we need to synchronize processors 23 * before calling pdc/iodc. 24 * 2) We should be checking the system state and not 25 * returning to the fault handler if things are really 26 * bad. 27 * 28 */ 29 30 .level 1.1 31 32 #include <asm/assembly.h> 33 #include <asm/pdc.h> 34 #include <asm/psw.h> 35 36 #include <linux/linkage.h> 37 #include <linux/init.h> 38 39 /* 40 * stack for os_hpmc, the HPMC handler. 41 * buffer for IODC procedures (for the HPMC handler). 42 * 43 * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc. 44 */ 45 46 .import toc_stack,data 47 #define hpmc_stack toc_stack /* re-use the TOC stack */ 48 49 #define HPMC_IODC_BUF_SIZE 0x8000 50 51 __PAGE_ALIGNED_BSS 52 .align 4096 53 hpmc_iodc_buf: 54 .block HPMC_IODC_BUF_SIZE 55 56 .section .bss 57 .align 8 58 hpmc_raddr: 59 .block 128 60 61 #define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */ 62 63 .section .bss 64 .align 8 65 ENTRY(hpmc_pim_data) 66 .block HPMC_PIM_DATA_SIZE 67 END(hpmc_pim_data) 68 69 .text 70 71 .import intr_save, code 72 .align 16 73 ENTRY(os_hpmc) 74 .os_hpmc: 75 76 /* 77 * registers modified: 78 * 79 * Using callee saves registers without saving them. The 80 * original values are in the pim dump if we need them. 81 * 82 * r2 (rp) return pointer 83 * r3 address of PDCE_PROC 84 * r4 scratch 85 * r5 scratch 86 * r23 (arg3) procedure arg 87 * r24 (arg2) procedure arg 88 * r25 (arg1) procedure arg 89 * r26 (arg0) procedure arg 90 * r30 (sp) stack pointer 91 * 92 * registers read: 93 * 94 * r26 contains address of PDCE_PROC on entry 95 * r28 (ret0) return value from procedure 96 */ 97 98 copy arg0, %r3 /* save address of PDCE_PROC */ 99 100 /* 101 * disable nested HPMCs 102 * 103 * Increment os_hpmc checksum to invalidate it. 104 * Do this before turning the PSW M bit off. 105 */ 106 107 mfctl %cr14, %r4 108 ldw 52(%r4),%r5 109 addi 1,%r5,%r5 110 stw %r5,52(%r4) 111 112 /* MP_FIXME: synchronize all processors. */ 113 114 /* Setup stack pointer. */ 115 116 load32 PA(hpmc_stack),sp 117 118 ldo 128(sp),sp /* leave room for arguments */ 119 120 /* 121 * Most PDC routines require that the M bit be off. 122 * So turn on the Q bit and turn off the M bit. 123 */ 124 125 ldi PSW_SM_Q,%r4 /* PSW Q on, PSW M off */ 126 mtctl %r4,ipsw 127 mtctl %r0,pcsq 128 mtctl %r0,pcsq 129 load32 PA(os_hpmc_1),%r4 130 mtctl %r4,pcoq 131 ldo 4(%r4),%r4 132 mtctl %r4,pcoq 133 rfi 134 nop 135 136 os_hpmc_1: 137 138 /* Call PDC_PIM to get HPMC pim info */ 139 140 /* 141 * Note that on some newer boxes, PDC_PIM must be called 142 * before PDC_IO if you want IO to be reset. PDC_PIM sets 143 * a flag that PDC_IO examines. 144 */ 145 146 ldo PDC_PIM(%r0), arg0 147 ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */ 148 load32 PA(hpmc_raddr),arg2 149 load32 PA(hpmc_pim_data),arg3 150 load32 HPMC_PIM_DATA_SIZE,%r4 151 stw %r4,-52(sp) 152 153 ldil L%PA(os_hpmc_2), rp 154 bv (r3) /* call pdce_proc */ 155 ldo R%PA(os_hpmc_2)(rp), rp 156 157 os_hpmc_2: 158 comib,<> 0,ret0, os_hpmc_fail 159 160 /* Reset IO by calling the hversion dependent PDC_IO routine */ 161 162 ldo PDC_IO(%r0),arg0 163 ldo 0(%r0),arg1 /* log IO errors */ 164 ldo 0(%r0),arg2 /* reserved */ 165 ldo 0(%r0),arg3 /* reserved */ 166 stw %r0,-52(sp) /* reserved */ 167 168 ldil L%PA(os_hpmc_3),rp 169 bv (%r3) /* call pdce_proc */ 170 ldo R%PA(os_hpmc_3)(rp),rp 171 172 os_hpmc_3: 173 174 /* FIXME? Check for errors from PDC_IO (-1 might be OK) */ 175 176 /* 177 * Initialize the IODC console device (HPA,SPA, path etc. 178 * are stored on page 0. 179 */ 180 181 /* 182 * Load IODC into hpmc_iodc_buf by calling PDC_IODC. 183 * Note that PDC_IODC handles flushing the appropriate 184 * data and instruction cache lines. 185 */ 186 187 ldo PDC_IODC(%r0),arg0 188 ldo PDC_IODC_READ(%r0),arg1 189 load32 PA(hpmc_raddr),arg2 190 ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */ 191 ldo PDC_IODC_RI_INIT(%r0),%r4 192 stw %r4,-52(sp) 193 load32 PA(hpmc_iodc_buf),%r4 194 stw %r4,-56(sp) 195 load32 HPMC_IODC_BUF_SIZE,%r4 196 stw %r4,-60(sp) 197 198 ldil L%PA(os_hpmc_4),rp 199 bv (%r3) /* call pdce_proc */ 200 ldo R%PA(os_hpmc_4)(rp),rp 201 202 os_hpmc_4: 203 comib,<> 0,ret0,os_hpmc_fail 204 205 /* Call the entry init (just loaded by PDC_IODC) */ 206 207 ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */ 208 ldo ENTRY_INIT_MOD_DEV(%r0), arg1 209 ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */ 210 depi 0,31,11,arg2 /* clear bits 21-31 */ 211 ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */ 212 load32 PA(hpmc_raddr),%r4 213 stw %r4, -52(sp) 214 stw %r0, -56(sp) /* HV */ 215 stw %r0, -60(sp) /* HV */ 216 stw %r0, -64(sp) /* HV */ 217 stw %r0, -68(sp) /* lang, must be zero */ 218 219 load32 PA(hpmc_iodc_buf),%r5 220 ldil L%PA(os_hpmc_5),rp 221 bv (%r5) 222 ldo R%PA(os_hpmc_5)(rp),rp 223 224 os_hpmc_5: 225 comib,<> 0,ret0,os_hpmc_fail 226 227 /* Prepare to call intr_save */ 228 229 /* 230 * Load kernel page directory (load into user also, since 231 * we don't intend to ever return to user land anyway) 232 */ 233 234 load32 PA(swapper_pg_dir),%r4 235 mtctl %r4,%cr24 /* Initialize kernel root pointer */ 236 mtctl %r4,%cr25 /* Initialize user root pointer */ 237 238 /* Clear sr4-sr7 */ 239 240 mtsp %r0, %sr4 241 mtsp %r0, %sr5 242 mtsp %r0, %sr6 243 mtsp %r0, %sr7 244 245 tovirt_r1 %r30 /* make sp virtual */ 246 247 rsm PSW_SM_Q,%r0 /* Clear Q bit */ 248 ldi 1,%r8 /* Set trap code to "1" for HPMC */ 249 load32 PA(intr_save),%r1 250 be 0(%sr7,%r1) 251 nop 252 253 os_hpmc_fail: 254 255 /* 256 * Reset the system 257 * 258 * Some systems may lockup from a broadcast reset, so try the 259 * hversion PDC_BROADCAST_RESET() first. 260 * MP_FIXME: reset all processors if more than one central bus. 261 */ 262 263 /* PDC_BROADCAST_RESET() */ 264 265 ldo PDC_BROADCAST_RESET(%r0),arg0 266 ldo 0(%r0),arg1 /* do reset */ 267 268 ldil L%PA(os_hpmc_6),rp 269 bv (%r3) /* call pdce_proc */ 270 ldo R%PA(os_hpmc_6)(rp),rp 271 272 os_hpmc_6: 273 274 /* 275 * possible return values: 276 * -1 non-existent procedure 277 * -2 non-existent option 278 * -16 unaligned stack 279 * 280 * If call returned, do a broadcast reset. 281 */ 282 283 ldil L%0xfffc0000,%r4 /* IO_BROADCAST */ 284 ldo 5(%r0),%r5 285 stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */ 286 287 b . 288 nop 289 .align 16 /* make function length multiple of 16 bytes */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.