|
@@ -396,3 +396,159 @@ titan_machine_check(unsigned long vector, unsigned long la_ptr)
|
|
/*
|
|
/*
|
|
* Mask of Titan interrupt sources which are reported as machine checks
|
|
* Mask of Titan interrupt sources which are reported as machine checks
|
|
*
|
|
*
|
|
|
|
+ * 63 - CChip Error
|
|
|
|
+ * 62 - PChip 0 H_Error
|
|
|
|
+ * 61 - PChip 1 H_Error
|
|
|
|
+ * 60 - PChip 0 C_Error
|
|
|
|
+ * 59 - PChip 1 C_Error
|
|
|
|
+ */
|
|
|
|
+#define TITAN_MCHECK_INTERRUPT_MASK 0xF800000000000000UL
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Sync the processor
|
|
|
|
+ */
|
|
|
|
+ mb();
|
|
|
|
+ draina();
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Only handle system errors here
|
|
|
|
+ */
|
|
|
|
+ if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
|
|
|
|
+ ev6_machine_check(vector, la_ptr);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * It's a system error, handle it here
|
|
|
|
+ *
|
|
|
|
+ * The PALcode has already cleared the error, so just parse it
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Parse the logout frame without printing first. If the only error(s)
|
|
|
|
+ * found are classified as "dismissable", then just dismiss them and
|
|
|
|
+ * don't print any message
|
|
|
|
+ */
|
|
|
|
+ if (titan_process_logout_frame(mchk_header, 0) !=
|
|
|
|
+ MCHK_DISPOSITION_DISMISS) {
|
|
|
|
+ char *saved_err_prefix = err_print_prefix;
|
|
|
|
+ err_print_prefix = KERN_CRIT;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Either a nondismissable error was detected or no
|
|
|
|
+ * recognized error was detected in the logout frame
|
|
|
|
+ * -- report the error in either case
|
|
|
|
+ */
|
|
|
|
+ printk("%s"
|
|
|
|
+ "*System %s Error (Vector 0x%x) reported on CPU %d:\n",
|
|
|
|
+ err_print_prefix,
|
|
|
|
+ (vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
|
|
|
|
+ (unsigned int)vector, (int)smp_processor_id());
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_VERBOSE_MCHECK
|
|
|
|
+ titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
|
|
|
|
+ if (alpha_verbose_mcheck)
|
|
|
|
+ dik_show_regs(get_irq_regs(), NULL);
|
|
|
|
+#endif /* CONFIG_VERBOSE_MCHECK */
|
|
|
|
+
|
|
|
|
+ err_print_prefix = saved_err_prefix;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Convert any pending interrupts which report as system
|
|
|
|
+ * machine checks to interrupts
|
|
|
|
+ */
|
|
|
|
+ irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
|
|
|
|
+ titan_dispatch_irqs(irqmask);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Release the logout frame
|
|
|
|
+ */
|
|
|
|
+ wrmces(0x7);
|
|
|
|
+ mb();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Subpacket Annotations
|
|
|
|
+ */
|
|
|
|
+static char *el_titan_pchip0_extended_annotation[] = {
|
|
|
|
+ "Subpacket Header", "P0_SCTL", "P0_SERREN",
|
|
|
|
+ "P0_APCTL", "P0_APERREN", "P0_AGPERREN",
|
|
|
|
+ "P0_ASPRST", "P0_AWSBA0", "P0_AWSBA1",
|
|
|
|
+ "P0_AWSBA2", "P0_AWSBA3", "P0_AWSM0",
|
|
|
|
+ "P0_AWSM1", "P0_AWSM2", "P0_AWSM3",
|
|
|
|
+ "P0_ATBA0", "P0_ATBA1", "P0_ATBA2",
|
|
|
|
+ "P0_ATBA3", "P0_GPCTL", "P0_GPERREN",
|
|
|
|
+ "P0_GSPRST", "P0_GWSBA0", "P0_GWSBA1",
|
|
|
|
+ "P0_GWSBA2", "P0_GWSBA3", "P0_GWSM0",
|
|
|
|
+ "P0_GWSM1", "P0_GWSM2", "P0_GWSM3",
|
|
|
|
+ "P0_GTBA0", "P0_GTBA1", "P0_GTBA2",
|
|
|
|
+ "P0_GTBA3", NULL
|
|
|
|
+};
|
|
|
|
+static char *el_titan_pchip1_extended_annotation[] = {
|
|
|
|
+ "Subpacket Header", "P1_SCTL", "P1_SERREN",
|
|
|
|
+ "P1_APCTL", "P1_APERREN", "P1_AGPERREN",
|
|
|
|
+ "P1_ASPRST", "P1_AWSBA0", "P1_AWSBA1",
|
|
|
|
+ "P1_AWSBA2", "P1_AWSBA3", "P1_AWSM0",
|
|
|
|
+ "P1_AWSM1", "P1_AWSM2", "P1_AWSM3",
|
|
|
|
+ "P1_ATBA0", "P1_ATBA1", "P1_ATBA2",
|
|
|
|
+ "P1_ATBA3", "P1_GPCTL", "P1_GPERREN",
|
|
|
|
+ "P1_GSPRST", "P1_GWSBA0", "P1_GWSBA1",
|
|
|
|
+ "P1_GWSBA2", "P1_GWSBA3", "P1_GWSM0",
|
|
|
|
+ "P1_GWSM1", "P1_GWSM2", "P1_GWSM3",
|
|
|
|
+ "P1_GTBA0", "P1_GTBA1", "P1_GTBA2",
|
|
|
|
+ "P1_GTBA3", NULL
|
|
|
|
+};
|
|
|
|
+static char *el_titan_memory_extended_annotation[] = {
|
|
|
|
+ "Subpacket Header", "AAR0", "AAR1",
|
|
|
|
+ "AAR2", "AAR3", "P0_SCTL",
|
|
|
|
+ "P0_GPCTL", "P0_APCTL", "P1_SCTL",
|
|
|
|
+ "P1_GPCTL", "P1_SCTL", NULL
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct el_subpacket_annotation el_titan_annotations[] = {
|
|
|
|
+ SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
|
|
|
|
+ EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
|
|
|
|
+ 1,
|
|
|
|
+ "Titan PChip 0 Extended Frame",
|
|
|
|
+ el_titan_pchip0_extended_annotation),
|
|
|
|
+ SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
|
|
|
|
+ EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
|
|
|
|
+ 1,
|
|
|
|
+ "Titan PChip 1 Extended Frame",
|
|
|
|
+ el_titan_pchip1_extended_annotation),
|
|
|
|
+ SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
|
|
|
|
+ EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
|
|
|
|
+ 1,
|
|
|
|
+ "Titan Memory Extended Frame",
|
|
|
|
+ el_titan_memory_extended_annotation),
|
|
|
|
+ SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
|
|
|
|
+ EL_TYPE__TERMINATION__TERMINATION,
|
|
|
|
+ 1,
|
|
|
|
+ "Termination Subpacket",
|
|
|
|
+ NULL)
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct el_subpacket *
|
|
|
|
+el_process_regatta_subpacket(struct el_subpacket *header)
|
|
|
|
+{
|
|
|
|
+ if (header->class != EL_CLASS__REGATTA_FAMILY) {
|
|
|
|
+ printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
|
|
|
|
+ err_print_prefix,
|
|
|
|
+ header->class, header->type);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch(header->type) {
|
|
|
|
+ case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
|
|
|
|
+ case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
|
|
|
|
+ case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
|
|
|
|
+ case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
|
|
|
|
+ case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
|
|
|
|
+ printk("%s ** Occurred on CPU %d:\n",
|
|
|
|
+ err_print_prefix,
|
|
|
|
+ (int)header->by_type.regatta_frame.cpuid);
|
|
|
|
+ privateer_process_logout_frame((struct el_common *)
|
|
|
|
+ header->by_type.regatta_frame.data_start, 1);
|
|
|
|
+ break;
|