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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * File: mca.c
  3.  * Purpose: Generic MCA handling layer
  4.  *
  5.  * Updated for latest kernel
  6.  * Copyright (C) 2002 Dell Computer Corporation
  7.  * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
  8.  *
  9.  * Copyright (C) 2002 Intel
  10.  * Copyright (C) Jenna Hall (jenna.s.hall@intel.com)
  11.  *
  12.  * Copyright (C) 2001 Intel
  13.  * Copyright (C) Fred Lewis (frederick.v.lewis@intel.com)
  14.  *
  15.  * Copyright (C) 2000 Intel
  16.  * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com)
  17.  *
  18.  * Copyright (C) 1999 Silicon Graphics, Inc.
  19.  * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
  20.  *
  21.  * 02/03/25 M. Domsch GUID cleanups
  22.  *
  23.  * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU
  24.  * error flag, set SAL default return values, changed
  25.  * error record structure to linked list, added init call
  26.  * to sal_get_state_info_size().
  27.  *
  28.  * 01/01/03 F. Lewis    Added setup of CMCI and CPEI IRQs, logging of corrected
  29.  *                      platform errors, completed code for logging of
  30.  *                      corrected & uncorrected machine check errors, and
  31.  *                      updated for conformance with Nov. 2000 revision of the
  32.  *                      SAL 3.0 spec.
  33.  * 00/03/29 C. Fleckenstein  Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
  34.  *                           added min save state dump, added INIT handler.
  35.  */
  36. #include <linux/config.h>
  37. #include <linux/types.h>
  38. #include <linux/init.h>
  39. #include <linux/sched.h>
  40. #include <linux/interrupt.h>
  41. #include <linux/irq.h>
  42. #include <linux/smp_lock.h>
  43. #include <linux/bootmem.h>
  44. #include <linux/acpi.h>
  45. #include <asm/machvec.h>
  46. #include <asm/page.h>
  47. #include <asm/ptrace.h>
  48. #include <asm/system.h>
  49. #include <asm/sal.h>
  50. #include <asm/mca.h>
  51. #include <asm/irq.h>
  52. #include <asm/hw_irq.h>
  53. #undef MCA_PRT_XTRA_DATA
  54. typedef struct ia64_fptr {
  55. unsigned long fp;
  56. unsigned long gp;
  57. } ia64_fptr_t;
  58. ia64_mc_info_t ia64_mc_info;
  59. ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state;
  60. ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state;
  61. u64 ia64_mca_proc_state_dump[512];
  62. u64 ia64_mca_stack[1024] __attribute__((aligned(16)));
  63. u64 ia64_mca_stackframe[32];
  64. u64 ia64_mca_bspstore[1024];
  65. u64 ia64_init_stack[INIT_TASK_SIZE] __attribute__((aligned(16)));
  66. u64 ia64_mca_sal_data_area[1356];
  67. u64 ia64_mca_min_state_save_info;
  68. u64 ia64_tlb_functional;
  69. u64 ia64_os_mca_recovery_successful;
  70. static void ia64_mca_wakeup_ipi_wait(void);
  71. static void ia64_mca_wakeup(int cpu);
  72. static void ia64_mca_wakeup_all(void);
  73. static void ia64_log_init(int);
  74. extern void ia64_monarch_init_handler (void);
  75. extern void ia64_slave_init_handler (void);
  76. extern struct hw_interrupt_type irq_type_iosapic_level;
  77. static struct irqaction cmci_irqaction = {
  78. handler:    ia64_mca_cmc_int_handler,
  79. flags:      SA_INTERRUPT,
  80. name:       "cmc_hndlr"
  81. };
  82. static struct irqaction mca_rdzv_irqaction = {
  83. handler:    ia64_mca_rendez_int_handler,
  84. flags:      SA_INTERRUPT,
  85. name:       "mca_rdzv"
  86. };
  87. static struct irqaction mca_wkup_irqaction = {
  88. handler:    ia64_mca_wakeup_int_handler,
  89. flags:      SA_INTERRUPT,
  90. name:       "mca_wkup"
  91. };
  92. static struct irqaction mca_cpe_irqaction = {
  93. handler:    ia64_mca_cpe_int_handler,
  94. flags:      SA_INTERRUPT,
  95. name:       "cpe_hndlr"
  96. };
  97. /*
  98.  *  ia64_mca_log_sal_error_record
  99.  *
  100.  *  This function retrieves a specified error record type from SAL, sends it to
  101.  *  the system log, and notifies SALs to clear the record from its non-volatile
  102.  *  memory.
  103.  *
  104.  *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT)
  105.  *  Outputs :   platform error status
  106.  */
  107. int
  108. ia64_mca_log_sal_error_record(int sal_info_type)
  109. {
  110. int platform_err = 0;
  111. /* Get the MCA error record */
  112. if (!ia64_log_get(sal_info_type, (prfunc_t)printk))
  113. return platform_err;                 // no record retrieved
  114. /* TODO:
  115.  * 1. analyze error logs to determine recoverability
  116.  * 2. perform error recovery procedures, if applicable
  117.  * 3. set ia64_os_mca_recovery_successful flag, if applicable
  118.  */
  119. platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
  120. ia64_sal_clear_state_info(sal_info_type);
  121. return platform_err;
  122. }
  123. /*
  124.  * platform dependent error handling
  125.  */
  126. #ifndef PLATFORM_MCA_HANDLERS
  127. void
  128. mca_handler_platform (void)
  129. {
  130. }
  131. void
  132. ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
  133. {
  134. IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. vector = %#xn", cpe_irq);
  135. /* Get the CMC error record and log it */
  136. ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
  137. }
  138. /*
  139.  * This routine will be used to deal with platform specific handling
  140.  * of the init, i.e. drop into the kernel debugger on server machine,
  141.  * or if the processor is part of some parallel machine without a
  142.  * console, then we would call the appropriate debug hooks here.
  143.  */
  144. void
  145. init_handler_platform (struct pt_regs *regs)
  146. {
  147. /* if a kernel debugger is available call it here else just dump the registers */
  148. show_regs(regs); /* dump the state info */
  149. while (1); /* hang city if no debugger */
  150. }
  151. /*
  152.  * ia64_mca_init_platform
  153.  *
  154.  *  External entry for platform specific MCA initialization.
  155.  *
  156.  *  Inputs
  157.  *      None
  158.  *
  159.  *  Outputs
  160.  *      None
  161.  */
  162. void
  163. ia64_mca_init_platform (void)
  164. {
  165. }
  166. /*
  167.  *  ia64_mca_check_errors
  168.  *
  169.  *  External entry to check for error records which may have been posted by SAL
  170.  *  for a prior failure which resulted in a machine shutdown before an the
  171.  *  error could be logged.  This function must be called after the filesystem
  172.  *  is initialized.
  173.  *
  174.  *  Inputs  :   None
  175.  *
  176.  *  Outputs :   None
  177.  */
  178. void
  179. ia64_mca_check_errors (void)
  180. {
  181. /*
  182.  *  If there is an MCA error record pending, get it and log it.
  183.  */
  184. ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
  185. }
  186. /*
  187.  * ia64_mca_register_cpev
  188.  *
  189.  *  Register the corrected platform error vector with SAL.
  190.  *
  191.  *  Inputs
  192.  *      cpev        Corrected Platform Error Vector number
  193.  *
  194.  *  Outputs
  195.  *      None
  196.  */
  197. static void
  198. ia64_mca_register_cpev (int cpev)
  199. {
  200. /* Register the CPE interrupt vector with SAL */
  201. if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) {
  202. printk("ia64_mca_platform_init: failed to register Corrected "
  203.        "Platform Error interrupt vector with SAL.n");
  204. return;
  205. }
  206. IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "
  207.        "vector %#x setup and enabledn", cpev);
  208. }
  209. #endif /* PLATFORM_MCA_HANDLERS */
  210. static char *min_state_labels[] = {
  211. "nat",
  212. "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
  213. "r9", "r10","r11", "r12","r13","r14", "r15",
  214. "b0r16","b0r17", "b0r18", "b0r19", "b0r20",
  215. "b0r21", "b0r22","b0r23", "b0r24", "b0r25",
  216. "b0r26", "b0r27", "b0r28","b0r29", "b0r30", "b0r31",
  217. "r16", "r17", "r18","r19", "r20", "r21","r22",
  218. "r23", "r24","r25", "r26", "r27","r28", "r29", "r30","r31",
  219. "preds", "br0", "rsc",
  220. "iip", "ipsr", "ifs",
  221. "xip", "xpsr", "xfs"
  222. };
  223. int ia64_pmss_dump_bank0=0;  /* dump bank 0 ? */
  224. /*
  225.  * routine to process and prepare to dump min_state_save
  226.  * information for debugging purposes.
  227.  *
  228.  */
  229. void
  230. ia64_process_min_state_save (pal_min_state_area_t *pmss, struct pt_regs *ptregs)
  231. {
  232. int i, max=57;
  233. u64 *tpmss_ptr=(u64 *)pmss;
  234. /* dump out the min_state_area information */
  235. for (i=0;i<max;i++) {
  236. if(!ia64_pmss_dump_bank0) {
  237. if(strncmp("B0",min_state_labels[i],2)==0) {
  238. tpmss_ptr++;  /* skip to next entry */
  239. continue;
  240. }
  241. }
  242. printk("%5s=0x%16.16lx ",min_state_labels[i],*tpmss_ptr++);
  243. if (((i+1)%3)==0 || ((!strcmp("GR16",min_state_labels[i]))
  244.      && !ia64_pmss_dump_bank0))
  245. printk("n");
  246. }
  247. }
  248. /*
  249.  * ia64_mca_cmc_vector_setup
  250.  *
  251.  *  Setup the corrected machine check vector register in the processor and
  252.  *  unmask interrupt.  This function is invoked on a per-processor basis.
  253.  *
  254.  * Inputs
  255.  *      None
  256.  *
  257.  * Outputs
  258.  * None
  259.  */
  260. void
  261. ia64_mca_cmc_vector_setup (void)
  262. {
  263. cmcv_reg_t cmcv;
  264. cmcv.cmcv_regval = 0;
  265. cmcv.cmcv_mask = 0;        /* Unmask/enable interrupt */
  266. cmcv.cmcv_vector = IA64_CMC_VECTOR;
  267. ia64_set_cmcv(cmcv.cmcv_regval);
  268. IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected "
  269.        "machine check vector %#x setup and enabled.n",
  270.        smp_processor_id(), IA64_CMC_VECTOR);
  271. IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lxn",
  272.        smp_processor_id(), ia64_get_cmcv());
  273. }
  274. #if defined(MCA_TEST)
  275. sal_log_processor_info_t slpi_buf;
  276. void
  277. mca_test(void)
  278. {
  279. slpi_buf.valid.psi_static_struct = 1;
  280. slpi_buf.valid.num_cache_check = 1;
  281. slpi_buf.valid.num_tlb_check = 1;
  282. slpi_buf.valid.num_bus_check = 1;
  283. slpi_buf.valid.processor_static_info.minstate = 1;
  284. slpi_buf.valid.processor_static_info.br = 1;
  285. slpi_buf.valid.processor_static_info.cr = 1;
  286. slpi_buf.valid.processor_static_info.ar = 1;
  287. slpi_buf.valid.processor_static_info.rr = 1;
  288. slpi_buf.valid.processor_static_info.fr = 1;
  289. ia64_os_mca_dispatch();
  290. }
  291. #endif /* #if defined(MCA_TEST) */
  292. /*
  293.  *  verify_guid
  294.  *
  295.  *  Compares a test guid to a target guid and returns result.
  296.  *
  297.  *  Inputs
  298.  *      test_guid *     (ptr to guid to be verified)
  299.  *      target_guid *   (ptr to standard guid to be verified against)
  300.  *
  301.  *  Outputs
  302.  *      0               (test verifies against target)
  303.  *      non-zero        (test guid does not verify)
  304.  */
  305. static int
  306. verify_guid (efi_guid_t *test, efi_guid_t *target)
  307. {
  308. int     rc;
  309. #ifdef IA64_MCA_DEBUG_INFO
  310. char out[40];
  311. #endif
  312. if ((rc = efi_guidcmp(*test, *target))) {
  313. IA64_MCA_DEBUG(KERN_DEBUG
  314.        "verify_guid: invalid GUID = %sn",
  315.        efi_guid_unparse(test, out));
  316. }
  317. return rc;
  318. }
  319. /*
  320.  * ia64_mca_init
  321.  *
  322.  *  Do all the system level mca specific initialization.
  323.  *
  324.  * 1. Register spinloop and wakeup request interrupt vectors
  325.  *
  326.  * 2. Register OS_MCA handler entry point
  327.  *
  328.  * 3. Register OS_INIT handler entry point
  329.  *
  330.  *  4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
  331.  *
  332.  *  Note that this initialization is done very early before some kernel
  333.  *  services are available.
  334.  *
  335.  *  Inputs  :   None
  336.  *
  337.  *  Outputs :   None
  338.  */
  339. void __init
  340. ia64_mca_init(void)
  341. {
  342. ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
  343. ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
  344. ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
  345. int i;
  346. s64 rc;
  347. IA64_MCA_DEBUG("ia64_mca_init: beginn");
  348. /* initialize recovery success indicator */
  349. ia64_os_mca_recovery_successful = 0;
  350. /* Clear the Rendez checkin flag for all cpus */
  351. for(i = 0 ; i < NR_CPUS; i++)
  352. ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
  353. /*
  354.  * Register the rendezvous spinloop and wakeup mechanism with SAL
  355.  */
  356. /* Register the rendezvous interrupt vector with SAL */
  357. if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
  358.  SAL_MC_PARAM_MECHANISM_INT,
  359.  IA64_MCA_RENDEZ_VECTOR,
  360.  IA64_MCA_RENDEZ_TIMEOUT,
  361.  0)))
  362. {
  363. printk("ia64_mca_init: Failed to register rendezvous interrupt "
  364.        "with SAL.  rc = %ldn", rc);
  365. return;
  366. }
  367. /* Register the wakeup interrupt vector with SAL */
  368. if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
  369.  SAL_MC_PARAM_MECHANISM_INT,
  370.  IA64_MCA_WAKEUP_VECTOR,
  371.  0, 0)))
  372. {
  373. printk("ia64_mca_init: Failed to register wakeup interrupt with SAL.  rc = %ldn",
  374.        rc);
  375. return;
  376. }
  377. IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.n");
  378. ia64_mc_info.imi_mca_handler        = __pa(mca_hldlr_ptr->fp);
  379. /*
  380.  * XXX - disable SAL checksum by setting size to 0; should be
  381.  * __pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch);
  382.  */
  383. ia64_mc_info.imi_mca_handler_size = 0;
  384. /* Register the os mca handler with SAL */
  385. if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
  386.        ia64_mc_info.imi_mca_handler,
  387.        mca_hldlr_ptr->gp,
  388.        ia64_mc_info.imi_mca_handler_size,
  389.        0, 0, 0)))
  390. {
  391. printk("ia64_mca_init: Failed to register os mca handler with SAL.  rc = %ldn",
  392.        rc);
  393. return;
  394. }
  395. IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lxn",
  396.        ia64_mc_info.imi_mca_handler, mca_hldlr_ptr->gp);
  397. /*
  398.  * XXX - disable SAL checksum by setting size to 0, should be
  399.  * IA64_INIT_HANDLER_SIZE
  400.  */
  401. ia64_mc_info.imi_monarch_init_handler = __pa(mon_init_ptr->fp);
  402. ia64_mc_info.imi_monarch_init_handler_size = 0;
  403. ia64_mc_info.imi_slave_init_handler = __pa(slave_init_ptr->fp);
  404. ia64_mc_info.imi_slave_init_handler_size = 0;
  405. IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lxn",
  406.        ia64_mc_info.imi_monarch_init_handler);
  407. /* Register the os init handler with SAL */
  408. if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
  409.        ia64_mc_info.imi_monarch_init_handler,
  410.        __pa(ia64_get_gp()),
  411.        ia64_mc_info.imi_monarch_init_handler_size,
  412.        ia64_mc_info.imi_slave_init_handler,
  413.        __pa(ia64_get_gp()),
  414.        ia64_mc_info.imi_slave_init_handler_size)))
  415. {
  416. printk("ia64_mca_init: Failed to register m/s init handlers with SAL. rc = %ldn",
  417.        rc);
  418. return;
  419. }
  420. IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SALn");
  421. /*
  422.  *  Configure the CMCI vector and handler. Interrupts for CMC are
  423.  *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
  424.  */
  425. register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
  426. ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */
  427. /* Setup the MCA rendezvous interrupt vector */
  428. register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
  429. /* Setup the MCA wakeup interrupt vector */
  430. register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
  431. /* Setup the CPE interrupt vector */
  432. {
  433. irq_desc_t *desc;
  434. unsigned int irq;
  435. int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
  436. if (cpev >= 0) {
  437. for (irq = 0; irq < NR_IRQS; ++irq)
  438. if (irq_to_vector(irq) == cpev) {
  439. desc = irq_desc(irq);
  440. desc->status |= IRQ_PER_CPU;
  441. desc->handler = &irq_type_iosapic_level;
  442. setup_irq(irq, &mca_cpe_irqaction);
  443. }
  444. ia64_mca_register_cpev(cpev);
  445. } else
  446. printk("ia64_mca_init: Failed to get routed CPEI vector from ACPI.n");
  447. }
  448. /* Initialize the areas set aside by the OS to buffer the
  449.  * platform/processor error states for MCA/INIT/CMC
  450.  * handling.
  451.  */
  452. ia64_log_init(SAL_INFO_TYPE_MCA);
  453. ia64_log_init(SAL_INFO_TYPE_INIT);
  454. ia64_log_init(SAL_INFO_TYPE_CMC);
  455. ia64_log_init(SAL_INFO_TYPE_CPE);
  456. /* Zero the min state save info */
  457. ia64_mca_min_state_save_info = 0;
  458. #if defined(MCA_TEST)
  459. mca_test();
  460. #endif /* #if defined(MCA_TEST) */
  461. printk("Mca related initialization donen");
  462. #if 0   // Too early in initialization -- error log is lost
  463. /* Do post-failure MCA error logging */
  464. ia64_mca_check_errors();
  465. #endif  // Too early in initialization -- error log is lost
  466. }
  467. /*
  468.  * ia64_mca_wakeup_ipi_wait
  469.  *
  470.  * Wait for the inter-cpu interrupt to be sent by the
  471.  * monarch processor once it is done with handling the
  472.  * MCA.
  473.  *
  474.  *  Inputs  :   None
  475.  *  Outputs :   None
  476.  */
  477. void
  478. ia64_mca_wakeup_ipi_wait(void)
  479. {
  480. int irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
  481. int irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
  482. u64 irr = 0;
  483. do {
  484. switch(irr_num) {
  485.       case 0:
  486. irr = ia64_get_irr0();
  487. break;
  488.       case 1:
  489. irr = ia64_get_irr1();
  490. break;
  491.       case 2:
  492. irr = ia64_get_irr2();
  493. break;
  494.       case 3:
  495. irr = ia64_get_irr3();
  496. break;
  497. }
  498. } while (!(irr & (1 << irr_bit))) ;
  499. }
  500. /*
  501.  * ia64_mca_wakeup
  502.  *
  503.  * Send an inter-cpu interrupt to wake-up a particular cpu
  504.  * and mark that cpu to be out of rendez.
  505.  *
  506.  *  Inputs  :   cpuid
  507.  *  Outputs :   None
  508.  */
  509. void
  510. ia64_mca_wakeup(int cpu)
  511. {
  512. platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
  513. ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
  514. }
  515. /*
  516.  * ia64_mca_wakeup_all
  517.  *
  518.  * Wakeup all the cpus which have rendez'ed previously.
  519.  *
  520.  *  Inputs  :   None
  521.  *  Outputs :   None
  522.  */
  523. void
  524. ia64_mca_wakeup_all(void)
  525. {
  526. int cpu;
  527. /* Clear the Rendez checkin flag for all cpus */
  528. for(cpu = 0; cpu < smp_num_cpus; cpu++)
  529. if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)
  530. ia64_mca_wakeup(cpu);
  531. }
  532. /*
  533.  * ia64_mca_rendez_interrupt_handler
  534.  *
  535.  * This is handler used to put slave processors into spinloop
  536.  * while the monarch processor does the mca handling and later
  537.  * wake each slave up once the monarch is done.
  538.  *
  539.  *  Inputs  :   None
  540.  *  Outputs :   None
  541.  */
  542. void
  543. ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
  544. {
  545. int flags, cpu = 0;
  546. /* Mask all interrupts */
  547. save_and_cli(flags);
  548. #ifdef CONFIG_SMP
  549. cpu = cpu_logical_id(hard_smp_processor_id());
  550. #endif
  551. ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
  552. /* Register with the SAL monarch that the slave has
  553.  * reached SAL
  554.  */
  555. ia64_sal_mc_rendez();
  556. /* Wait for the wakeup IPI from the monarch
  557.  * This waiting is done by polling on the wakeup-interrupt
  558.  * vector bit in the processor's IRRs
  559.  */
  560. ia64_mca_wakeup_ipi_wait();
  561. /* Enable all interrupts */
  562. restore_flags(flags);
  563. }
  564. /*
  565.  * ia64_mca_wakeup_int_handler
  566.  *
  567.  * The interrupt handler for processing the inter-cpu interrupt to the
  568.  * slave cpu which was spinning in the rendez loop.
  569.  * Since this spinning is done by turning off the interrupts and
  570.  * polling on the wakeup-interrupt bit in the IRR, there is
  571.  * nothing useful to be done in the handler.
  572.  *
  573.  *  Inputs  :   wakeup_irq  (Wakeup-interrupt bit)
  574.  * arg (Interrupt handler specific argument)
  575.  * ptregs (Exception frame at the time of the interrupt)
  576.  *  Outputs :   None
  577.  *
  578.  */
  579. void
  580. ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
  581. {
  582. }
  583. /*
  584.  * ia64_return_to_sal_check
  585.  *
  586.  * This is function called before going back from the OS_MCA handler
  587.  * to the OS_MCA dispatch code which finally takes the control back
  588.  * to the SAL.
  589.  * The main purpose of this routine is to setup the OS_MCA to SAL
  590.  * return state which can be used by the OS_MCA dispatch code
  591.  * just before going back to SAL.
  592.  *
  593.  *  Inputs  :   None
  594.  *  Outputs :   None
  595.  */
  596. void
  597. ia64_return_to_sal_check(void)
  598. {
  599. /* Copy over some relevant stuff from the sal_to_os_mca_handoff
  600.  * so that it can be used at the time of os_mca_to_sal_handoff
  601.  */
  602. ia64_os_to_sal_handoff_state.imots_sal_gp =
  603. ia64_sal_to_os_handoff_state.imsto_sal_gp;
  604. ia64_os_to_sal_handoff_state.imots_sal_check_ra =
  605. ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
  606. /* Cold Boot for uncorrectable MCA */
  607. ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
  608. /* Default = tell SAL to return to same context */
  609. ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;
  610. /* Register pointer to new min state values */
  611. /* NOTE: need to do something with this during recovery phase */
  612. ia64_os_to_sal_handoff_state.imots_new_min_state = &ia64_mca_min_state_save_info;
  613. }
  614. /*
  615.  * ia64_mca_ucmc_handler
  616.  *
  617.  * This is uncorrectable machine check handler called from OS_MCA
  618.  * dispatch code which is in turn called from SAL_CHECK().
  619.  * This is the place where the core of OS MCA handling is done.
  620.  * Right now the logs are extracted and displayed in a well-defined
  621.  * format. This handler code is supposed to be run only on the
  622.  * monarch processor. Once the monarch is done with MCA handling
  623.  * further MCA logging is enabled by clearing logs.
  624.  * Monarch also has the duty of sending wakeup-IPIs to pull the
  625.  * slave processors out of rendezvous spinloop.
  626.  *
  627.  *  Inputs  :   None
  628.  *  Outputs :   None
  629.  */
  630. void
  631. ia64_mca_ucmc_handler(void)
  632. {
  633. int platform_err = 0;
  634. /* Get the MCA error record and log it */
  635. platform_err = ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
  636. /*
  637.  *  Do Platform-specific mca error handling if required.
  638.  */
  639. if (platform_err)
  640. mca_handler_platform();
  641. /*
  642.  *  Wakeup all the processors which are spinning in the rendezvous
  643.  *  loop.
  644.  */
  645. ia64_mca_wakeup_all();
  646. /* Return to SAL */
  647. ia64_return_to_sal_check();
  648. }
  649. /*
  650.  * ia64_mca_cmc_int_handler
  651.  *
  652.  *  This is corrected machine check interrupt handler.
  653.  * Right now the logs are extracted and displayed in a well-defined
  654.  * format.
  655.  *
  656.  * Inputs
  657.  *      interrupt number
  658.  *      client data arg ptr
  659.  *      saved registers ptr
  660.  *
  661.  * Outputs
  662.  * None
  663.  */
  664. void
  665. ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
  666. {
  667. IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %dn",
  668.        cmc_irq, smp_processor_id());
  669. /* Get the CMC error record and log it */
  670. ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
  671. }
  672. /*
  673.  * IA64_MCA log support
  674.  */
  675. #define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */
  676. #define IA64_MAX_LOG_TYPES      4   /* MCA, INIT, CMC, CPE */
  677. typedef struct ia64_state_log_s
  678. {
  679. spinlock_t isl_lock;
  680. int isl_index;
  681. ia64_err_rec_t  *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
  682. } ia64_state_log_t;
  683. static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
  684. #define IA64_LOG_ALLOCATE(it, size) 
  685. {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = 
  686. (ia64_err_rec_t *)alloc_bootmem(size); 
  687. ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = 
  688. (ia64_err_rec_t *)alloc_bootmem(size);}
  689. #define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
  690. #define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
  691. #define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
  692. #define IA64_LOG_NEXT_INDEX(it)    ia64_state_log[it].isl_index
  693. #define IA64_LOG_CURR_INDEX(it)    1 - ia64_state_log[it].isl_index
  694. #define IA64_LOG_INDEX_INC(it) 
  695.     ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
  696. #define IA64_LOG_INDEX_DEC(it) 
  697.     ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
  698. #define IA64_LOG_NEXT_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
  699. #define IA64_LOG_CURR_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
  700. /*
  701.  * C portion of the OS INIT handler
  702.  *
  703.  * Called from ia64_monarch_init_handler
  704.  *
  705.  * Inputs: pointer to pt_regs where processor info was saved.
  706.  *
  707.  * Returns:
  708.  *   0 if SAL must warm boot the System
  709.  *   1 if SAL must return to interrupted context using PAL_MC_RESUME
  710.  *
  711.  */
  712. void
  713. ia64_init_handler (struct pt_regs *regs)
  714. {
  715. sal_log_processor_info_t *proc_ptr;
  716. ia64_err_rec_t *plog_ptr;
  717. printk("Entered OS INIT handlern");
  718. /* Get the INIT processor log */
  719. if (!ia64_log_get(SAL_INFO_TYPE_INIT, (prfunc_t)printk))
  720. return;                 // no record retrieved
  721. #ifdef IA64_DUMP_ALL_PROC_INFO
  722. ia64_log_print(SAL_INFO_TYPE_INIT, (prfunc_t)printk);
  723. #endif
  724. /*
  725.  * get pointer to min state save area
  726.  *
  727.  */
  728. plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
  729. proc_ptr = &plog_ptr->proc_err;
  730. ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area,
  731.     regs);
  732. /* Clear the INIT SAL logs now that they have been saved in the OS buffer */
  733. ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
  734. init_handler_platform(regs);              /* call platform specific routines */
  735. }
  736. /*
  737.  *  ia64_log_prt_guid
  738.  *
  739.  *  Print a formatted GUID.
  740.  *
  741.  * Inputs   :   p_guid      (ptr to the GUID)
  742.  *              prfunc      (print function)
  743.  * Outputs  :   None
  744.  *
  745.  */
  746. void
  747. ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc)
  748. {
  749. char out[40];
  750. printk(KERN_DEBUG "GUID = %sn", efi_guid_unparse(p_guid, out));
  751. }
  752. static void
  753. ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc)
  754. {
  755. int i, j;
  756. if (!p)
  757. return;
  758. for (i = 0; i < n_ch;) {
  759. prfunc("%p ", (void *)p);
  760. for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) {
  761. prfunc("%02x ", *p);
  762. }
  763. prfunc("n");
  764. }
  765. }
  766. #ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
  767. static void
  768. ia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc)
  769. {
  770. prfunc("SAL RECORD HEADER:  Record buffer = %p,  header size = %ldn",
  771.        (void *)rh, sizeof(sal_log_record_header_t));
  772. ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t),
  773.  (prfunc_t)prfunc);
  774. prfunc("Total record length = %dn", rh->len);
  775. ia64_log_prt_guid(&rh->platform_guid, prfunc);
  776. prfunc("End of SAL RECORD HEADERn");
  777. }
  778. static void
  779. ia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc)
  780. {
  781. prfunc("SAL SECTION HEADER:  Record buffer = %p,  header size = %ldn",
  782.        (void *)sh, sizeof(sal_log_section_hdr_t));
  783. ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t),
  784.  (prfunc_t)prfunc);
  785. prfunc("Length of section & header = %dn", sh->len);
  786. ia64_log_prt_guid(&sh->guid, prfunc);
  787. prfunc("End of SAL SECTION HEADERn");
  788. }
  789. #endif  // MCA_PRT_XTRA_DATA for test only @FVL
  790. /*
  791.  * ia64_log_init
  792.  * Reset the OS ia64 log buffer
  793.  * Inputs   :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
  794.  * Outputs : None
  795.  */
  796. void
  797. ia64_log_init(int sal_info_type)
  798. {
  799. u64 max_size = 0;
  800. IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
  801. IA64_LOG_LOCK_INIT(sal_info_type);
  802. // SAL will tell us the maximum size of any error record of this type
  803. max_size = ia64_sal_get_state_info_size(sal_info_type);
  804. // set up OS data structures to hold error info
  805. IA64_LOG_ALLOCATE(sal_info_type, max_size);
  806. memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size);
  807. memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size);
  808. }
  809. /*
  810.  * ia64_log_get
  811.  *
  812.  * Get the current MCA log from SAL and copy it into the OS log buffer.
  813.  *
  814.  *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
  815.  *              prfunc      (fn ptr of log output function)
  816.  *  Outputs :   size        (total record length)
  817.  *
  818.  */
  819. u64
  820. ia64_log_get(int sal_info_type, prfunc_t prfunc)
  821. {
  822. sal_log_record_header_t     *log_buffer;
  823. u64                         total_len = 0;
  824. int                         s;
  825. IA64_LOG_LOCK(sal_info_type);
  826. /* Get the process state information */
  827. log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
  828. total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
  829. if (total_len) {
  830. IA64_LOG_INDEX_INC(sal_info_type);
  831. IA64_LOG_UNLOCK(sal_info_type);
  832. IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
  833.        "Record length = %ldn", sal_info_type, total_len);
  834. return total_len;
  835. } else {
  836. IA64_LOG_UNLOCK(sal_info_type);
  837. prfunc("ia64_log_get: No SAL error record available for type %dn", sal_info_type);
  838. return 0;
  839. }
  840. }
  841. /*
  842.  *  ia64_log_prt_oem_data
  843.  *
  844.  *  Print OEM specific data if included.
  845.  *
  846.  * Inputs   :   header_len  (length passed in section header)
  847.  *              sect_len    (default length of section type)
  848.  *              p_data      (ptr to data)
  849.  * prfunc (print function)
  850.  * Outputs : None
  851.  *
  852.  */
  853. void
  854. ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
  855. {
  856. int oem_data_len, i;
  857. if ((oem_data_len = header_len - sect_len) > 0) {
  858. prfunc(" OEM Specific Data:");
  859. for (i = 0; i < oem_data_len; i++, p_data++)
  860. prfunc(" %02x", *p_data);
  861. }
  862. prfunc("n");
  863. }
  864. /*
  865.  *  ia64_log_rec_header_print
  866.  *
  867.  *  Log info from the SAL error record header.
  868.  *
  869.  *  Inputs  :   lh *    (ptr to SAL log error record header)
  870.  *              prfunc  (fn ptr of log output function to use)
  871.  *  Outputs :   None
  872.  */
  873. void
  874. ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
  875. {
  876. char str_buf[32];
  877. sprintf(str_buf, "%2d.%02d",
  878. (lh->revision.major >> 4) * 10 + (lh->revision.major & 0xf),
  879. (lh->revision.minor >> 4) * 10 + (lh->revision.minor & 0xf));
  880. prfunc("+Err Record ID: %d    SAL Rev: %sn", lh->id, str_buf);
  881. sprintf(str_buf, "%02d/%02d/%04d/ %02d:%02d:%02d",
  882. (lh->timestamp.slh_month >> 4) * 10 +
  883. (lh->timestamp.slh_month & 0xf),
  884. (lh->timestamp.slh_day >> 4) * 10 +
  885. (lh->timestamp.slh_day & 0xf),
  886. (lh->timestamp.slh_century >> 4) * 1000 +
  887. (lh->timestamp.slh_century & 0xf) * 100 +
  888. (lh->timestamp.slh_year >> 4) * 10 +
  889. (lh->timestamp.slh_year & 0xf),
  890. (lh->timestamp.slh_hour >> 4) * 10 +
  891. (lh->timestamp.slh_hour & 0xf),
  892. (lh->timestamp.slh_minute >> 4) * 10 +
  893. (lh->timestamp.slh_minute & 0xf),
  894. (lh->timestamp.slh_second >> 4) * 10 +
  895. (lh->timestamp.slh_second & 0xf));
  896. prfunc("+Time: %s    Severity %dn", str_buf, lh->severity);
  897. }
  898. /*
  899.  * ia64_log_processor_regs_print
  900.  * Print the contents of the saved processor register(s) in the format
  901.  * <reg_prefix>[<index>] <value>
  902.  *
  903.  * Inputs : regs (Register save buffer)
  904.  * reg_num (# of registers)
  905.  * reg_class (application/banked/control/bank1_general)
  906.  * reg_prefix (ar/br/cr/b1_gr)
  907.  * Outputs : None
  908.  *
  909.  */
  910. void
  911. ia64_log_processor_regs_print(u64 *regs,
  912.       int reg_num,
  913.       char *reg_class,
  914.       char *reg_prefix,
  915.       prfunc_t prfunc)
  916. {
  917. int i;
  918. prfunc("+%s Registersn", reg_class);
  919. for (i = 0; i < reg_num; i++)
  920. prfunc("+ %s[%d] 0x%lxn", reg_prefix, i, regs[i]);
  921. }
  922. /*
  923.  * ia64_log_processor_fp_regs_print
  924.  *  Print the contents of the saved floating page register(s) in the format
  925.  *      <reg_prefix>[<index>] <value>
  926.  *
  927.  * Inputs:  ia64_fpreg  (Register save buffer)
  928.  *          reg_num     (# of registers)
  929.  *          reg_class   (application/banked/control/bank1_general)
  930.  *          reg_prefix  (ar/br/cr/b1_gr)
  931.  * Outputs: None
  932.  *
  933.  */
  934. void
  935. ia64_log_processor_fp_regs_print (struct ia64_fpreg *regs,
  936.                                   int               reg_num,
  937.                                   char              *reg_class,
  938.                                   char              *reg_prefix,
  939.                                   prfunc_t          prfunc)
  940. {
  941. int i;
  942. prfunc("+%s Registersn", reg_class);
  943. for (i = 0; i < reg_num; i++)
  944. prfunc("+ %s[%d] 0x%lx%016lxn", reg_prefix, i, regs[i].u.bits[1],
  945.        regs[i].u.bits[0]);
  946. }
  947. static char *pal_mesi_state[] = {
  948. "Invalid",
  949. "Shared",
  950. "Exclusive",
  951. "Modified",
  952. "Reserved1",
  953. "Reserved2",
  954. "Reserved3",
  955. "Reserved4"
  956. };
  957. static char *pal_cache_op[] = {
  958. "Unknown",
  959. "Move in",
  960. "Cast out",
  961. "Coherency check",
  962. "Internal",
  963. "Instruction fetch",
  964. "Implicit Writeback",
  965. "Reserved"
  966. };
  967. /*
  968.  * ia64_log_cache_check_info_print
  969.  * Display the machine check information related to cache error(s).
  970.  * Inputs:  i           (Multiple errors are logged, i - index of logged error)
  971.  *          cc_info *   (Ptr to cache check info logged by the PAL and later
  972.  *  captured by the SAL)
  973.  *          prfunc      (fn ptr of print function to be used for output)
  974.  * Outputs: None
  975.  */
  976. void
  977. ia64_log_cache_check_info_print (int                      i,
  978.                                  sal_log_mod_error_info_t *cache_check_info,
  979.  prfunc_t prfunc)
  980. {
  981. pal_cache_check_info_t  *info;
  982. u64                     target_addr;
  983. if (!cache_check_info->valid.check_info) {
  984. IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]n",i);
  985. return;                 /* If check info data not valid, skip it */
  986. }
  987. info        = (pal_cache_check_info_t *)&cache_check_info->check_info;
  988. target_addr = cache_check_info->target_identifier;
  989. prfunc("+ Cache check info[%d]n+", i);
  990. prfunc("  Level: L%d,",info->level);
  991. if (info->mv)
  992. prfunc(" Mesi: %s,",pal_mesi_state[info->mesi]);
  993. prfunc(" Index: %d,", info->index);
  994. if (info->ic)
  995. prfunc(" Cache: Instruction,");
  996. if (info->dc)
  997. prfunc(" Cache: Data,");
  998. if (info->tl)
  999. prfunc(" Line: Tag,");
  1000. if (info->dl)
  1001. prfunc(" Line: Data,");
  1002. prfunc(" Operation: %s,", pal_cache_op[info->op]);
  1003. if (info->wv)
  1004. prfunc(" Way: %d,", info->way);
  1005. if (cache_check_info->valid.target_identifier)
  1006. /* Hope target address is saved in target_identifier */
  1007. if (info->tv)
  1008. prfunc(" Target Addr: 0x%lx,", target_addr);
  1009. if (info->mc)
  1010. prfunc(" MC: Corrected");
  1011. prfunc("n");
  1012. }
  1013. /*
  1014.  * ia64_log_tlb_check_info_print
  1015.  * Display the machine check information related to tlb error(s).
  1016.  * Inputs:  i           (Multiple errors are logged, i - index of logged error)
  1017.  *          tlb_info *  (Ptr to machine check info logged by the PAL and later
  1018.  *  captured by the SAL)
  1019.  *          prfunc      (fn ptr of print function to be used for output)
  1020.  * Outputs: None
  1021.  */
  1022. void
  1023. ia64_log_tlb_check_info_print (int                      i,
  1024.                                sal_log_mod_error_info_t *tlb_check_info,
  1025.                                prfunc_t                 prfunc)
  1026. {
  1027. pal_tlb_check_info_t    *info;
  1028. if (!tlb_check_info->valid.check_info) {
  1029. IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]n", i);
  1030. return;                 /* If check info data not valid, skip it */
  1031. }
  1032. info = (pal_tlb_check_info_t *)&tlb_check_info->check_info;
  1033. prfunc("+ TLB Check Info [%d]n+", i);
  1034. if (info->itc)
  1035. prfunc("  Failure: Instruction Translation Cache");
  1036. if (info->dtc)
  1037. prfunc("  Failure: Data Translation Cache");
  1038. if (info->itr) {
  1039. prfunc("  Failure: Instruction Translation Register");
  1040. prfunc(" ,Slot: %d", info->tr_slot);
  1041. }
  1042. if (info->dtr) {
  1043. prfunc("  Failure: Data Translation Register");
  1044. prfunc(" ,Slot: %d", info->tr_slot);
  1045. }
  1046. if (info->mc)
  1047. prfunc(" ,MC: Corrected");
  1048. prfunc("n");
  1049. }
  1050. /*
  1051.  * ia64_log_bus_check_info_print
  1052.  * Display the machine check information related to bus error(s).
  1053.  * Inputs:  i           (Multiple errors are logged, i - index of logged error)
  1054.  *          bus_info *  (Ptr to machine check info logged by the PAL and later
  1055.  *  captured by the SAL)
  1056.  *          prfunc      (fn ptr of print function to be used for output)
  1057.  * Outputs: None
  1058.  */
  1059. void
  1060. ia64_log_bus_check_info_print (int                      i,
  1061.                                sal_log_mod_error_info_t *bus_check_info,
  1062.                                prfunc_t                 prfunc)
  1063. {
  1064. pal_bus_check_info_t *info;
  1065. u64         req_addr;   /* Address of the requestor of the transaction */
  1066. u64         resp_addr;  /* Address of the responder of the transaction */
  1067. u64         targ_addr;  /* Address where the data was to be delivered to */
  1068. /* or obtained from */
  1069. if (!bus_check_info->valid.check_info) {
  1070. IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]n", i);
  1071. return;                 /* If check info data not valid, skip it */
  1072. }
  1073. info      = (pal_bus_check_info_t *)&bus_check_info->check_info;
  1074. req_addr  = bus_check_info->requestor_identifier;
  1075. resp_addr = bus_check_info->responder_identifier;
  1076. targ_addr = bus_check_info->target_identifier;
  1077. prfunc("+ BUS Check Info [%d]n+", i);
  1078. prfunc(" Status Info: %d", info->bsi);
  1079. prfunc(" ,Severity: %d", info->sev);
  1080. prfunc(" ,Transaction Type: %d", info->type);
  1081. prfunc(" ,Transaction Size: %d", info->size);
  1082. if (info->cc)
  1083. prfunc(" ,Cache-cache-transfer");
  1084. if (info->ib)
  1085. prfunc(" ,Error: Internal");
  1086. if (info->eb)
  1087. prfunc(" ,Error: External");
  1088. if (info->mc)
  1089. prfunc(" ,MC: Corrected");
  1090. if (info->tv)
  1091. prfunc(" ,Target Address: 0x%lx", targ_addr);
  1092. if (info->rq)
  1093. prfunc(" ,Requestor Address: 0x%lx", req_addr);
  1094. if (info->tv)
  1095. prfunc(" ,Responder Address: 0x%lx", resp_addr);
  1096. prfunc("n");
  1097. }
  1098. /*
  1099.  *  ia64_log_mem_dev_err_info_print
  1100.  *
  1101.  *  Format and log the platform memory device error record section data.
  1102.  *
  1103.  *  Inputs:  mem_dev_err_info * (Ptr to memory device error record section
  1104.  *                               returned by SAL)
  1105.  *           prfunc             (fn ptr of print function to be used for output)
  1106.  *  Outputs: None
  1107.  */
  1108. void
  1109. ia64_log_mem_dev_err_info_print (sal_log_mem_dev_err_info_t *mdei,
  1110.                                  prfunc_t                   prfunc)
  1111. {
  1112. prfunc("+ Mem Error Detail: ");
  1113. if (mdei->valid.error_status)
  1114. prfunc(" Error Status: %#lx,", mdei->error_status);
  1115. if (mdei->valid.physical_addr)
  1116. prfunc(" Physical Address: %#lx,", mdei->physical_addr);
  1117. if (mdei->valid.addr_mask)
  1118. prfunc(" Address Mask: %#lx,", mdei->addr_mask);
  1119. if (mdei->valid.node)
  1120. prfunc(" Node: %d,", mdei->node);
  1121. if (mdei->valid.card)
  1122. prfunc(" Card: %d,", mdei->card);
  1123. if (mdei->valid.module)
  1124. prfunc(" Module: %d,", mdei->module);
  1125. if (mdei->valid.bank)
  1126. prfunc(" Bank: %d,", mdei->bank);
  1127. if (mdei->valid.device)
  1128. prfunc(" Device: %d,", mdei->device);
  1129. if (mdei->valid.row)
  1130. prfunc(" Row: %d,", mdei->row);
  1131. if (mdei->valid.column)
  1132. prfunc(" Column: %d,", mdei->column);
  1133. if (mdei->valid.bit_position)
  1134. prfunc(" Bit Position: %d,", mdei->bit_position);
  1135. if (mdei->valid.target_id)
  1136. prfunc(" ,Target Address: %#lx,", mdei->target_id);
  1137. if (mdei->valid.requestor_id)
  1138. prfunc(" ,Requestor Address: %#lx,", mdei->requestor_id);
  1139. if (mdei->valid.responder_id)
  1140. prfunc(" ,Responder Address: %#lx,", mdei->responder_id);
  1141. if (mdei->valid.bus_spec_data)
  1142. prfunc(" Bus Specific Data: %#lx,", mdei->bus_spec_data);
  1143. prfunc("n");
  1144. if (mdei->valid.oem_id) {
  1145. u8  *p_data = &(mdei->oem_id[0]);
  1146. int i;
  1147. prfunc(" OEM Memory Controller ID:");
  1148. for (i = 0; i < 16; i++, p_data++)
  1149. prfunc(" %02x", *p_data);
  1150. prfunc("n");
  1151. }
  1152. if (mdei->valid.oem_data) {
  1153. platform_mem_dev_err_print((int)mdei->header.len,
  1154.       (int)sizeof(sal_log_mem_dev_err_info_t) - 1,
  1155.       &(mdei->oem_data[0]), prfunc);
  1156. }
  1157. }
  1158. /*
  1159.  *  ia64_log_sel_dev_err_info_print
  1160.  *
  1161.  *  Format and log the platform SEL device error record section data.
  1162.  *
  1163.  *  Inputs:  sel_dev_err_info * (Ptr to the SEL device error record section
  1164.  *                               returned by SAL)
  1165.  *           prfunc             (fn ptr of print function to be used for output)
  1166.  *  Outputs: None
  1167.  */
  1168. void
  1169. ia64_log_sel_dev_err_info_print (sal_log_sel_dev_err_info_t *sdei,
  1170.                                  prfunc_t                   prfunc)
  1171. {
  1172. int     i;
  1173. prfunc("+ SEL Device Error Detail: ");
  1174. if (sdei->valid.record_id)
  1175. prfunc(" Record ID: %#x", sdei->record_id);
  1176. if (sdei->valid.record_type)
  1177. prfunc(" Record Type: %#x", sdei->record_type);
  1178. prfunc(" Time Stamp: ");
  1179. for (i = 0; i < 4; i++)
  1180. prfunc("%1d", sdei->timestamp[i]);
  1181. if (sdei->valid.generator_id)
  1182. prfunc(" Generator ID: %#x", sdei->generator_id);
  1183. if (sdei->valid.evm_rev)
  1184. prfunc(" Message Format Version: %#x", sdei->evm_rev);
  1185. if (sdei->valid.sensor_type)
  1186. prfunc(" Sensor Type: %#x", sdei->sensor_type);
  1187. if (sdei->valid.sensor_num)
  1188. prfunc(" Sensor Number: %#x", sdei->sensor_num);
  1189. if (sdei->valid.event_dir)
  1190. prfunc(" Event Direction Type: %#x", sdei->event_dir);
  1191. if (sdei->valid.event_data1)
  1192. prfunc(" Data1: %#x", sdei->event_data1);
  1193. if (sdei->valid.event_data2)
  1194. prfunc(" Data2: %#x", sdei->event_data2);
  1195. if (sdei->valid.event_data3)
  1196. prfunc(" Data3: %#x", sdei->event_data3);
  1197. prfunc("n");
  1198. }
  1199. /*
  1200.  *  ia64_log_pci_bus_err_info_print
  1201.  *
  1202.  *  Format and log the platform PCI bus error record section data.
  1203.  *
  1204.  *  Inputs:  pci_bus_err_info * (Ptr to the PCI bus error record section
  1205.  *                               returned by SAL)
  1206.  *           prfunc             (fn ptr of print function to be used for output)
  1207.  *  Outputs: None
  1208.  */
  1209. void
  1210. ia64_log_pci_bus_err_info_print (sal_log_pci_bus_err_info_t *pbei,
  1211.                                  prfunc_t                   prfunc)
  1212. {
  1213. prfunc("+ PCI Bus Error Detail: ");
  1214. if (pbei->valid.err_status)
  1215. prfunc(" Error Status: %#lx", pbei->err_status);
  1216. if (pbei->valid.err_type)
  1217. prfunc(" Error Type: %#x", pbei->err_type);
  1218. if (pbei->valid.bus_id)
  1219. prfunc(" Bus ID: %#x", pbei->bus_id);
  1220. if (pbei->valid.bus_address)
  1221. prfunc(" Bus Address: %#lx", pbei->bus_address);
  1222. if (pbei->valid.bus_data)
  1223. prfunc(" Bus Data: %#lx", pbei->bus_data);
  1224. if (pbei->valid.bus_cmd)
  1225. prfunc(" Bus Command: %#lx", pbei->bus_cmd);
  1226. if (pbei->valid.requestor_id)
  1227. prfunc(" Requestor ID: %#lx", pbei->requestor_id);
  1228. if (pbei->valid.responder_id)
  1229. prfunc(" Responder ID: %#lx", pbei->responder_id);
  1230. if (pbei->valid.target_id)
  1231. prfunc(" Target ID: %#lx", pbei->target_id);
  1232. if (pbei->valid.oem_data)
  1233. prfunc("n");
  1234. if (pbei->valid.oem_data) {
  1235. platform_pci_bus_err_print((int)pbei->header.len,
  1236.       (int)sizeof(sal_log_pci_bus_err_info_t) - 1,
  1237.       &(pbei->oem_data[0]), prfunc);
  1238. }
  1239. }
  1240. /*
  1241.  *  ia64_log_smbios_dev_err_info_print
  1242.  *
  1243.  *  Format and log the platform SMBIOS device error record section data.
  1244.  *
  1245.  *  Inputs:  smbios_dev_err_info * (Ptr to the SMBIOS device error record
  1246.  *                                  section returned by SAL)
  1247.  *           prfunc             (fn ptr of print function to be used for output)
  1248.  *  Outputs: None
  1249.  */
  1250. void
  1251. ia64_log_smbios_dev_err_info_print (sal_log_smbios_dev_err_info_t *sdei,
  1252.                                     prfunc_t                      prfunc)
  1253. {
  1254. u8      i;
  1255. prfunc("+ SMBIOS Device Error Detail: ");
  1256. if (sdei->valid.event_type)
  1257. prfunc(" Event Type: %#x", sdei->event_type);
  1258. if (sdei->valid.time_stamp) {
  1259. prfunc(" Time Stamp: ");
  1260. for (i = 0; i < 6; i++)
  1261. prfunc("%d", sdei->time_stamp[i]);
  1262. }
  1263. if ((sdei->valid.data) && (sdei->valid.length)) {
  1264. prfunc(" Data: ");
  1265. for (i = 0; i < sdei->length; i++)
  1266. prfunc(" %02x", sdei->data[i]);
  1267. }
  1268. prfunc("n");
  1269. }
  1270. /*
  1271.  *  ia64_log_pci_comp_err_info_print
  1272.  *
  1273.  *  Format and log the platform PCI component error record section data.
  1274.  *
  1275.  *  Inputs:  pci_comp_err_info * (Ptr to the PCI component error record section
  1276.  *                                returned by SAL)
  1277.  *           prfunc             (fn ptr of print function to be used for output)
  1278.  *  Outputs: None
  1279.  */
  1280. void
  1281. ia64_log_pci_comp_err_info_print(sal_log_pci_comp_err_info_t *pcei,
  1282.  prfunc_t                     prfunc)
  1283. {
  1284. u32     n_mem_regs, n_io_regs;
  1285. u64     i, n_pci_data;
  1286. u64     *p_reg_data;
  1287. u8      *p_oem_data;
  1288. prfunc("+ PCI Component Error Detail: ");
  1289. if (pcei->valid.err_status)
  1290. prfunc(" Error Status: %#lxn", pcei->err_status);
  1291. if (pcei->valid.comp_info)
  1292. prfunc(" Component Info: Vendor Id = %#x, Device Id = %#x,"
  1293.        " Class Code = %#x, Seg/Bus/Dev/Func = %d/%d/%d/%dn",
  1294.        pcei->comp_info.vendor_id, pcei->comp_info.device_id,
  1295.        pcei->comp_info.class_code, pcei->comp_info.seg_num,
  1296.        pcei->comp_info.bus_num, pcei->comp_info.dev_num,
  1297.        pcei->comp_info.func_num);
  1298. n_mem_regs = (pcei->valid.num_mem_regs) ? pcei->num_mem_regs : 0;
  1299. n_io_regs =  (pcei->valid.num_io_regs)  ? pcei->num_io_regs  : 0;
  1300. p_reg_data = &(pcei->reg_data_pairs[0]);
  1301. p_oem_data = (u8 *)p_reg_data +
  1302. (n_mem_regs + n_io_regs) * 2 * sizeof(u64);
  1303. n_pci_data = p_oem_data - (u8 *)pcei;
  1304. if (n_pci_data > pcei->header.len) {
  1305. prfunc(" Invalid PCI Component Error Record format: length = %ld, "
  1306.        " Size PCI Data = %d, Num Mem-Map/IO-Map Regs = %ld/%ldn",
  1307.        pcei->header.len, n_pci_data, n_mem_regs, n_io_regs);
  1308. return;
  1309. }
  1310. if (n_mem_regs) {
  1311. prfunc(" Memory Mapped Registersn Address tValuen");
  1312. for (i = 0; i < pcei->num_mem_regs; i++) {
  1313. prfunc(" %#lx %#lxn", p_reg_data[0], p_reg_data[1]);
  1314. p_reg_data += 2;
  1315. }
  1316. }
  1317. if (n_io_regs) {
  1318. prfunc(" I/O Mapped Registersn Address tValuen");
  1319. for (i = 0; i < pcei->num_io_regs; i++) {
  1320. prfunc(" %#lx %#lxn", p_reg_data[0], p_reg_data[1]);
  1321. p_reg_data += 2;
  1322. }
  1323. }
  1324. if (pcei->valid.oem_data) {
  1325. platform_pci_comp_err_print((int)pcei->header.len, n_pci_data,
  1326.       p_oem_data, prfunc);
  1327. prfunc("n");
  1328. }
  1329. }
  1330. /*
  1331.  *  ia64_log_plat_specific_err_info_print
  1332.  *
  1333.  *  Format and log the platform specifie error record section data.
  1334.  *
  1335.  *  Inputs:  sel_dev_err_info * (Ptr to the platform specific error record
  1336.  *                               section returned by SAL)
  1337.  *           prfunc             (fn ptr of print function to be used for output)
  1338.  *  Outputs: None
  1339.  */
  1340. void
  1341. ia64_log_plat_specific_err_info_print (sal_log_plat_specific_err_info_t *psei,
  1342.                                        prfunc_t                         prfunc)
  1343. {
  1344. prfunc("+ Platform Specific Error Detail: ");
  1345. if (psei->valid.err_status)
  1346. prfunc(" Error Status: %#lx", psei->err_status);
  1347. if (psei->valid.guid) {
  1348. prfunc(" GUID: ");
  1349. ia64_log_prt_guid(&psei->guid, prfunc);
  1350. }
  1351. if (psei->valid.oem_data) {
  1352. platform_plat_specific_err_print((int)psei->header.len,
  1353.       (int)sizeof(sal_log_plat_specific_err_info_t) - 1,
  1354.       &(psei->oem_data[0]), prfunc);
  1355. }
  1356. prfunc("n");
  1357. }
  1358. /*
  1359.  *  ia64_log_host_ctlr_err_info_print
  1360.  *
  1361.  *  Format and log the platform host controller error record section data.
  1362.  *
  1363.  *  Inputs:  host_ctlr_err_info * (Ptr to the host controller error record
  1364.  *                                 section returned by SAL)
  1365.  *           prfunc             (fn ptr of print function to be used for output)
  1366.  *  Outputs: None
  1367.  */
  1368. void
  1369. ia64_log_host_ctlr_err_info_print (sal_log_host_ctlr_err_info_t *hcei,
  1370.                                    prfunc_t                     prfunc)
  1371. {
  1372. prfunc("+ Host Controller Error Detail: ");
  1373. if (hcei->valid.err_status)
  1374. prfunc(" Error Status: %#lx", hcei->err_status);
  1375. if (hcei->valid.requestor_id)
  1376. prfunc(" Requestor ID: %#lx", hcei->requestor_id);
  1377. if (hcei->valid.responder_id)
  1378. prfunc(" Responder ID: %#lx", hcei->responder_id);
  1379. if (hcei->valid.target_id)
  1380. prfunc(" Target ID: %#lx", hcei->target_id);
  1381. if (hcei->valid.bus_spec_data)
  1382. prfunc(" Bus Specific Data: %#lx", hcei->bus_spec_data);
  1383. if (hcei->valid.oem_data) {
  1384. platform_host_ctlr_err_print((int)hcei->header.len,
  1385.       (int)sizeof(sal_log_host_ctlr_err_info_t) - 1,
  1386.       &(hcei->oem_data[0]), prfunc);
  1387. }
  1388. prfunc("n");
  1389. }
  1390. /*
  1391.  *  ia64_log_plat_bus_err_info_print
  1392.  *
  1393.  *  Format and log the platform bus error record section data.
  1394.  *
  1395.  *  Inputs:  plat_bus_err_info * (Ptr to the platform bus error record section
  1396.  *                                returned by SAL)
  1397.  *           prfunc             (fn ptr of print function to be used for output)
  1398.  *  Outputs: None
  1399.  */
  1400. void
  1401. ia64_log_plat_bus_err_info_print (sal_log_plat_bus_err_info_t *pbei,
  1402.                                   prfunc_t                    prfunc)
  1403. {
  1404. prfunc("+ Platform Bus Error Detail: ");
  1405. if (pbei->valid.err_status)
  1406. prfunc(" Error Status: %#lx", pbei->err_status);
  1407. if (pbei->valid.requestor_id)
  1408. prfunc(" Requestor ID: %#lx", pbei->requestor_id);
  1409. if (pbei->valid.responder_id)
  1410. prfunc(" Responder ID: %#lx", pbei->responder_id);
  1411. if (pbei->valid.target_id)
  1412. prfunc(" Target ID: %#lx", pbei->target_id);
  1413. if (pbei->valid.bus_spec_data)
  1414. prfunc(" Bus Specific Data: %#lx", pbei->bus_spec_data);
  1415. if (pbei->valid.oem_data) {
  1416. platform_plat_bus_err_print((int)pbei->header.len,
  1417.       (int)sizeof(sal_log_plat_bus_err_info_t) - 1,
  1418.       &(pbei->oem_data[0]), prfunc);
  1419. }
  1420. prfunc("n");
  1421. }
  1422. /*
  1423.  *  ia64_log_proc_dev_err_info_print
  1424.  *
  1425.  *  Display the processor device error record.
  1426.  *
  1427.  *  Inputs:  sal_log_processor_info_t * (Ptr to processor device error record
  1428.  *                                       section body).
  1429.  *           prfunc                     (fn ptr of print function to be used
  1430.  *                                       for output).
  1431.  *  Outputs: None
  1432.  */
  1433. void
  1434. ia64_log_proc_dev_err_info_print (sal_log_processor_info_t  *slpi,
  1435.                                   prfunc_t                  prfunc)
  1436. {
  1437. #ifdef MCA_PRT_XTRA_DATA
  1438. size_t  d_len = slpi->header.len - sizeof(sal_log_section_hdr_t);
  1439. #endif
  1440. sal_processor_static_info_t *spsi;
  1441. int                         i;
  1442. sal_log_mod_error_info_t    *p_data;
  1443. prfunc("+Processor Device Error Info Sectionn");
  1444. #ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
  1445. {
  1446. char    *p_data = (char *)&slpi->valid;
  1447. prfunc("SAL_PROC_DEV_ERR SECTION DATA:  Data buffer = %p, "
  1448.        "Data size = %ldn", (void *)p_data, d_len);
  1449. ia64_log_hexdump(p_data, d_len, prfunc);
  1450. prfunc("End of SAL_PROC_DEV_ERR SECTION DATAn");
  1451. }
  1452. #endif  // MCA_PRT_XTRA_DATA for test only @FVL
  1453. if (slpi->valid.proc_error_map)
  1454. prfunc(" Processor Error Map: %#lxn", slpi->proc_error_map);
  1455. if (slpi->valid.proc_state_param)
  1456. prfunc(" Processor State Param: %#lxn", slpi->proc_state_parameter);
  1457. if (slpi->valid.proc_cr_lid)
  1458. prfunc(" Processor LID: %#lxn", slpi->proc_cr_lid);
  1459. /*
  1460.  *  Note: March 2001 SAL spec states that if the number of elements in any
  1461.  *  of  the MOD_ERROR_INFO_STRUCT arrays is zero, the entire array is
  1462.  *  absent. Also, current implementations only allocate space for number of
  1463.  *  elements used.  So we walk the data pointer from here on.
  1464.  */
  1465. p_data = &slpi->cache_check_info[0];
  1466. /* Print the cache check information if any*/
  1467. for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
  1468. ia64_log_cache_check_info_print(i, p_data, prfunc);
  1469. /* Print the tlb check information if any*/
  1470. for (i = 0 ; i < slpi->valid.num_tlb_check; i++, p_data++)
  1471. ia64_log_tlb_check_info_print(i, p_data, prfunc);
  1472. /* Print the bus check information if any*/
  1473. for (i = 0 ; i < slpi->valid.num_bus_check; i++, p_data++)
  1474. ia64_log_bus_check_info_print(i, p_data, prfunc);
  1475. /* Print the reg file check information if any*/
  1476. for (i = 0 ; i < slpi->valid.num_reg_file_check; i++, p_data++)
  1477. ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
  1478.  prfunc);    /* Just hex dump for now */
  1479. /* Print the ms check information if any*/
  1480. for (i = 0 ; i < slpi->valid.num_ms_check; i++, p_data++)
  1481. ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
  1482.  prfunc);    /* Just hex dump for now */
  1483. /* Print CPUID registers if any*/
  1484. if (slpi->valid.cpuid_info) {
  1485. u64     *p = (u64 *)p_data;
  1486. prfunc(" CPUID Regs: %#lx %#lx %#lx %#lxn", p[0], p[1], p[2], p[3]);
  1487. p_data++;
  1488. }
  1489. /* Print processor static info if any */
  1490. if (slpi->valid.psi_static_struct) {
  1491. spsi = (sal_processor_static_info_t *)p_data;
  1492. /* Print branch register contents if valid */
  1493. if (spsi->valid.br)
  1494. ia64_log_processor_regs_print(spsi->br, 8, "Branch", "br",
  1495.       prfunc);
  1496. /* Print control register contents if valid */
  1497. if (spsi->valid.cr)
  1498. ia64_log_processor_regs_print(spsi->cr, 128, "Control", "cr",
  1499.       prfunc);
  1500. /* Print application register contents if valid */
  1501. if (spsi->valid.ar)
  1502. ia64_log_processor_regs_print(spsi->ar, 128, "Application",
  1503.       "ar", prfunc);
  1504. /* Print region register contents if valid */
  1505. if (spsi->valid.rr)
  1506. ia64_log_processor_regs_print(spsi->rr, 8, "Region", "rr",
  1507.       prfunc);
  1508. /* Print floating-point register contents if valid */
  1509. if (spsi->valid.fr)
  1510. ia64_log_processor_fp_regs_print(spsi->fr, 128, "Floating-point", "fr",
  1511.  prfunc);
  1512. }
  1513. }
  1514. /*
  1515.  * ia64_log_processor_info_print
  1516.  *
  1517.  * Display the processor-specific information logged by PAL as a part
  1518.  * of MCA or INIT or CMC.
  1519.  *
  1520.  *  Inputs   :  lh      (Pointer of the sal log header which specifies the
  1521.  *                       format of SAL state info as specified by the SAL spec).
  1522.  *              prfunc  (fn ptr of print function to be used for output).
  1523.  * Outputs : None
  1524.  */
  1525. void
  1526. ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc)
  1527. {
  1528. sal_log_section_hdr_t       *slsh;
  1529. int                         n_sects;
  1530. int                         ercd_pos;
  1531. if (!lh)
  1532. return;
  1533. #ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
  1534. ia64_log_prt_record_header(lh, prfunc);
  1535. #endif  // MCA_PRT_XTRA_DATA for test only @FVL
  1536. if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
  1537. IA64_MCA_DEBUG("ia64_mca_log_print: "
  1538.        "truncated SAL CMC error record. len = %dn",
  1539.        lh->len);
  1540. return;
  1541. }
  1542. /* Print record header info */
  1543. ia64_log_rec_header_print(lh, prfunc);
  1544. for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
  1545. /* point to next section header */
  1546. slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
  1547. #ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
  1548. ia64_log_prt_section_header(slsh, prfunc);
  1549. #endif  // MCA_PRT_XTRA_DATA for test only @FVL
  1550. if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) {
  1551. IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record sectionn");
  1552. continue;
  1553. }
  1554. /*
  1555.  *  Now process processor device error record section
  1556.  */
  1557. ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh,
  1558.  printk);
  1559. }
  1560. IA64_MCA_DEBUG("ia64_mca_log_print: "
  1561.        "found %d sections in SAL CMC error record. len = %dn",
  1562.        n_sects, lh->len);
  1563. if (!n_sects) {
  1564. prfunc("No Processor Device Error Info Section foundn");
  1565. return;
  1566. }
  1567. }
  1568. /*
  1569.  *  ia64_log_platform_info_print
  1570.  *
  1571.  *  Format and Log the SAL Platform Error Record.
  1572.  *
  1573.  *  Inputs  :   lh      (Pointer to the sal error record header with format
  1574.  *                       specified by the SAL spec).
  1575.  *              prfunc  (fn ptr of log output function to use)
  1576.  *  Outputs : platform error status
  1577.  */
  1578. int
  1579. ia64_log_platform_info_print (sal_log_record_header_t *lh, prfunc_t prfunc)
  1580. {
  1581. sal_log_section_hdr_t *slsh;
  1582. int n_sects;
  1583. int ercd_pos;
  1584. int platform_err = 0;
  1585. if (!lh)
  1586. return platform_err;
  1587. #ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
  1588. ia64_log_prt_record_header(lh, prfunc);
  1589. #endif  // MCA_PRT_XTRA_DATA for test only @FVL
  1590. if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
  1591. IA64_MCA_DEBUG("ia64_mca_log_print: "
  1592.        "truncated SAL error record. len = %dn",
  1593.        lh->len);
  1594. return platform_err;
  1595. }
  1596. /* Print record header info */
  1597. ia64_log_rec_header_print(lh, prfunc);
  1598. for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
  1599. /* point to next section header */
  1600. slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
  1601. #ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
  1602. ia64_log_prt_section_header(slsh, prfunc);
  1603. if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) != 0) {
  1604. size_t  d_len = slsh->len - sizeof(sal_log_section_hdr_t);
  1605. char    *p_data = (char *)&((sal_log_mem_dev_err_info_t *)slsh)->valid;
  1606. prfunc("Start of Platform Err Data Section:  Data buffer = %p, "
  1607.        "Data size = %ldn", (void *)p_data, d_len);
  1608. ia64_log_hexdump(p_data, d_len, prfunc);
  1609. prfunc("End of Platform Err Data Sectionn");
  1610. }
  1611. #endif  // MCA_PRT_XTRA_DATA for test only @FVL
  1612. /*
  1613.  *  Now process CPE error record section
  1614.  */
  1615. if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) == 0) {
  1616. ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh,
  1617.  prfunc);
  1618. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
  1619. platform_err = 1;
  1620. prfunc("+Platform Memory Device Error Info Sectionn");
  1621. ia64_log_mem_dev_err_info_print((sal_log_mem_dev_err_info_t *)slsh,
  1622. prfunc);
  1623. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID) == 0) {
  1624. platform_err = 1;
  1625. prfunc("+Platform SEL Device Error Info Sectionn");
  1626. ia64_log_sel_dev_err_info_print((sal_log_sel_dev_err_info_t *)slsh,
  1627. prfunc);
  1628. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID) == 0) {
  1629. platform_err = 1;
  1630. prfunc("+Platform PCI Bus Error Info Sectionn");
  1631. ia64_log_pci_bus_err_info_print((sal_log_pci_bus_err_info_t *)slsh,
  1632. prfunc);
  1633. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID) == 0) {
  1634. platform_err = 1;
  1635. prfunc("+Platform SMBIOS Device Error Info Sectionn");
  1636. ia64_log_smbios_dev_err_info_print((sal_log_smbios_dev_err_info_t *)slsh,
  1637.    prfunc);
  1638. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID) == 0) {
  1639. platform_err = 1;
  1640. prfunc("+Platform PCI Component Error Info Sectionn");
  1641. ia64_log_pci_comp_err_info_print((sal_log_pci_comp_err_info_t *)slsh,
  1642.  prfunc);
  1643. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) {
  1644. platform_err = 1;
  1645. prfunc("+Platform Specific Error Info Sectionn");
  1646. ia64_log_plat_specific_err_info_print((sal_log_plat_specific_err_info_t *)
  1647.       slsh,
  1648.       prfunc);
  1649. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID) == 0) {
  1650. platform_err = 1;
  1651. prfunc("+Platform Host Controller Error Info Sectionn");
  1652. ia64_log_host_ctlr_err_info_print((sal_log_host_ctlr_err_info_t *)slsh,
  1653.   prfunc);
  1654. } else if (efi_guidcmp(slsh->guid, SAL_PLAT_BUS_ERR_SECT_GUID) == 0) {
  1655. platform_err = 1;
  1656. prfunc("+Platform Bus Error Info Sectionn");
  1657. ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh,
  1658.  prfunc);
  1659. } else {
  1660. IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record sectionn");
  1661. continue;
  1662. }
  1663. }
  1664. IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %dn",
  1665.        n_sects, lh->len);
  1666. if (!n_sects) {
  1667. prfunc("No Platform Error Info Sections foundn");
  1668. return platform_err;
  1669. }
  1670. return platform_err;
  1671. }
  1672. /*
  1673.  * ia64_log_print
  1674.  *
  1675.  *  Displays the contents of the OS error log information
  1676.  *
  1677.  *  Inputs   :  info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
  1678.  *              prfunc      (fn ptr of log output function to use)
  1679.  * Outputs : platform error status
  1680.  */
  1681. int
  1682. ia64_log_print(int sal_info_type, prfunc_t prfunc)
  1683. {
  1684. int platform_err = 0;
  1685. switch(sal_info_type) {
  1686.       case SAL_INFO_TYPE_MCA:
  1687. prfunc("+BEGIN HARDWARE ERROR STATE AT MCAn");
  1688. platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
  1689. prfunc("+END HARDWARE ERROR STATE AT MCAn");
  1690. break;
  1691.       case SAL_INFO_TYPE_INIT:
  1692. prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)n");
  1693. break;
  1694.       case SAL_INFO_TYPE_CMC:
  1695. prfunc("+BEGIN HARDWARE ERROR STATE AT CMCn");
  1696. ia64_log_processor_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
  1697. prfunc("+END HARDWARE ERROR STATE AT CMCn");
  1698. break;
  1699.       case SAL_INFO_TYPE_CPE:
  1700. prfunc("+BEGIN HARDWARE ERROR STATE AT CPEn");
  1701. ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
  1702. prfunc("+END HARDWARE ERROR STATE AT CPEn");
  1703. break;
  1704.       default:
  1705. prfunc("+MCA UNKNOWN ERROR LOG (UNIMPLEMENTED)n");
  1706. break;
  1707. }
  1708. return platform_err;
  1709. }