hpmc.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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