mca.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:54k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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