root/arch/parisc/kernel/hpmc.S

/* [<][>][^][v][top][bottom][index][help] */
   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         __PAGE_ALIGNED_BSS
  47         .align 4096
  48 hpmc_stack:
  49         .block 16384
  50 
  51 #define HPMC_IODC_BUF_SIZE 0x8000
  52 
  53         __PAGE_ALIGNED_BSS
  54         .align 4096
  55 hpmc_iodc_buf:
  56         .block HPMC_IODC_BUF_SIZE
  57 
  58         .section .bss
  59         .align 8
  60 hpmc_raddr:
  61         .block 128
  62 
  63 #define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
  64 
  65         .section .bss
  66         .align 8
  67 ENTRY(hpmc_pim_data)
  68         .block HPMC_PIM_DATA_SIZE
  69 END(hpmc_pim_data)
  70 
  71         .text
  72 
  73         .import intr_save, code
  74         .align 16
  75 ENTRY(os_hpmc)
  76 .os_hpmc:
  77 
  78         /*
  79          * registers modified:
  80          *
  81          *   Using callee saves registers without saving them.  The
  82          *   original values are in the pim dump if we need them.
  83          *
  84          *   r2   (rp)  return pointer
  85          *   r3   address of PDCE_PROC
  86          *   r4   scratch
  87          *   r5   scratch
  88          *   r23  (arg3) procedure arg
  89          *   r24  (arg2) procedure arg
  90          *   r25  (arg1) procedure arg
  91          *   r26  (arg0) procedure arg
  92          *   r30  (sp)   stack pointer
  93          *
  94          * registers read:
  95          *
  96          *   r26  contains address of PDCE_PROC on entry
  97          *   r28  (ret0) return value from procedure
  98          */
  99 
 100         copy    arg0, %r3       /* save address of PDCE_PROC */
 101 
 102         /*
 103          *  disable nested HPMCs
 104          *
 105          * Increment os_hpmc checksum to invalidate it.
 106          * Do this before turning the PSW M bit off.
 107          */
 108 
 109         mfctl   %cr14, %r4
 110         ldw     52(%r4),%r5
 111         addi    1,%r5,%r5
 112         stw     %r5,52(%r4)
 113 
 114         /* MP_FIXME: synchronize all processors. */
 115 
 116         /* Setup stack pointer. */
 117 
 118         load32  PA(hpmc_stack),sp
 119         
 120         ldo     128(sp),sp /* leave room for arguments */
 121 
 122         /*
 123          * Most PDC routines require that the M bit be off.
 124          * So turn on the Q bit and turn off the M bit.
 125          */
 126 
 127         ldi     PSW_SM_Q,%r4                   /* PSW Q on, PSW M off */
 128         mtctl   %r4,ipsw
 129         mtctl   %r0,pcsq
 130         mtctl   %r0,pcsq
 131         load32  PA(os_hpmc_1),%r4
 132         mtctl   %r4,pcoq
 133         ldo     4(%r4),%r4
 134         mtctl   %r4,pcoq
 135         rfi
 136         nop
 137 
 138 os_hpmc_1:
 139 
 140         /* Call PDC_PIM to get HPMC pim info */
 141 
 142         /*
 143          * Note that on some newer boxes, PDC_PIM must be called
 144          * before PDC_IO if you want IO to be reset. PDC_PIM sets
 145          * a flag that PDC_IO examines.
 146          */
 147 
 148         ldo     PDC_PIM(%r0), arg0
 149         ldo     PDC_PIM_HPMC(%r0),arg1          /* Transfer HPMC data */
 150         load32  PA(hpmc_raddr),arg2
 151         load32  PA(hpmc_pim_data),arg3
 152         load32  HPMC_PIM_DATA_SIZE,%r4
 153         stw     %r4,-52(sp)
 154 
 155         ldil    L%PA(os_hpmc_2), rp
 156         bv      (r3)                            /* call pdce_proc */
 157         ldo     R%PA(os_hpmc_2)(rp), rp
 158 
 159 os_hpmc_2:
 160         comib,<>  0,ret0, os_hpmc_fail
 161 
 162         /* Reset IO by calling the hversion dependent PDC_IO routine */
 163 
 164         ldo     PDC_IO(%r0),arg0
 165         ldo     0(%r0),arg1                     /* log IO errors */
 166         ldo     0(%r0),arg2                     /* reserved */
 167         ldo     0(%r0),arg3                     /* reserved */
 168         stw     %r0,-52(sp)                     /* reserved */
 169 
 170         ldil    L%PA(os_hpmc_3),rp
 171         bv      (%r3)                           /* call pdce_proc */
 172         ldo     R%PA(os_hpmc_3)(rp),rp
 173 
 174 os_hpmc_3:
 175 
 176         /* FIXME? Check for errors from PDC_IO (-1 might be OK) */
 177 
 178         /*
 179          * Initialize the IODC console device (HPA,SPA, path etc.
 180          * are stored on page 0.
 181          */
 182 
 183         /*
 184          * Load IODC into hpmc_iodc_buf by calling PDC_IODC.
 185          * Note that PDC_IODC handles flushing the appropriate
 186          * data and instruction cache lines.
 187          */
 188 
 189         ldo     PDC_IODC(%r0),arg0
 190         ldo     PDC_IODC_READ(%r0),arg1
 191         load32  PA(hpmc_raddr),arg2
 192         ldw     BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
 193         ldo     PDC_IODC_RI_INIT(%r0),%r4
 194         stw     %r4,-52(sp)
 195         load32  PA(hpmc_iodc_buf),%r4
 196         stw     %r4,-56(sp)
 197         load32  HPMC_IODC_BUF_SIZE,%r4
 198         stw     %r4,-60(sp)
 199 
 200         ldil    L%PA(os_hpmc_4),rp
 201         bv      (%r3)                            /* call pdce_proc */
 202         ldo     R%PA(os_hpmc_4)(rp),rp
 203 
 204 os_hpmc_4:
 205         comib,<>  0,ret0,os_hpmc_fail
 206 
 207         /* Call the entry init (just loaded by PDC_IODC) */
 208 
 209         ldw     BOOT_CONSOLE_HPA_OFFSET(%r0),arg0  /* console hpa */
 210         ldo     ENTRY_INIT_MOD_DEV(%r0), arg1
 211         ldw     BOOT_CONSOLE_SPA_OFFSET(%r0),arg2  /* console spa */
 212         depi    0,31,11,arg2                       /* clear bits 21-31    */
 213         ldo     BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
 214         load32  PA(hpmc_raddr),%r4
 215         stw     %r4, -52(sp)
 216         stw     %r0, -56(sp)                    /* HV                  */
 217         stw     %r0, -60(sp)                    /* HV                  */
 218         stw     %r0, -64(sp)                    /* HV                  */
 219         stw     %r0, -68(sp)                    /* lang, must be zero  */
 220 
 221         load32  PA(hpmc_iodc_buf),%r5
 222         ldil    L%PA(os_hpmc_5),rp
 223         bv      (%r5)
 224         ldo     R%PA(os_hpmc_5)(rp),rp
 225 
 226 os_hpmc_5:
 227         comib,<>  0,ret0,os_hpmc_fail
 228 
 229         /* Prepare to call intr_save */
 230 
 231         /*
 232          * Load kernel page directory (load into user also, since
 233          * we don't intend to ever return to user land anyway)
 234          */
 235 
 236         load32          PA(swapper_pg_dir),%r4
 237         mtctl           %r4,%cr24       /* Initialize kernel root pointer */
 238         mtctl           %r4,%cr25       /* Initialize user root pointer */
 239 
 240         /* Clear sr4-sr7 */
 241 
 242         mtsp    %r0, %sr4
 243         mtsp    %r0, %sr5
 244         mtsp    %r0, %sr6
 245         mtsp    %r0, %sr7
 246 
 247         tovirt_r1 %r30      /* make sp virtual */
 248 
 249         rsm     PSW_SM_Q,%r0           /* Clear Q bit */
 250         ldi     1,%r8       /* Set trap code to "1" for HPMC */
 251         load32  PA(intr_save),%r1
 252         be      0(%sr7,%r1)
 253         nop
 254 
 255 os_hpmc_fail:
 256 
 257         /*
 258          * Reset the system
 259          *
 260          * Some systems may lockup from a broadcast reset, so try the
 261          * hversion PDC_BROADCAST_RESET() first.
 262          * MP_FIXME: reset all processors if more than one central bus.
 263          */
 264 
 265         /* PDC_BROADCAST_RESET() */
 266 
 267         ldo     PDC_BROADCAST_RESET(%r0),arg0
 268         ldo     0(%r0),arg1                     /* do reset */
 269 
 270         ldil    L%PA(os_hpmc_6),rp
 271         bv      (%r3)                           /* call pdce_proc */
 272         ldo     R%PA(os_hpmc_6)(rp),rp
 273 
 274 os_hpmc_6:
 275 
 276         /*
 277          * possible return values:
 278          *  -1  non-existent procedure
 279          *  -2  non-existent option
 280          *  -16 unaligned stack
 281          *
 282          * If call returned, do a broadcast reset.
 283          */
 284 
 285         ldil    L%0xfffc0000,%r4        /* IO_BROADCAST */
 286         ldo     5(%r0),%r5
 287         stw     %r5,48(%r4)             /*  CMD_RESET to IO_COMMAND offset */
 288 
 289         b .
 290         nop
 291         .align 16       /* make function length multiple of 16 bytes */
 292 .os_hpmc_end:
 293 
 294 
 295         __INITRODATA
 296 .globl os_hpmc_size
 297         .align 4
 298         .type   os_hpmc_size, @object
 299         .size   os_hpmc_size, 4
 300 os_hpmc_size:
 301         .word .os_hpmc_end-.os_hpmc

/* [<][>][^][v][top][bottom][index][help] */