aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/mca.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/mca.c')
-rw-r--r--arch/ia64/kernel/mca.c84
1 files changed, 55 insertions, 29 deletions
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 87fb7cecead0..b57e723f194c 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -281,11 +281,6 @@ ia64_mca_log_sal_error_record(int sal_info_type)
281 ia64_sal_clear_state_info(sal_info_type); 281 ia64_sal_clear_state_info(sal_info_type);
282} 282}
283 283
284/*
285 * platform dependent error handling
286 */
287#ifndef PLATFORM_MCA_HANDLERS
288
289#ifdef CONFIG_ACPI 284#ifdef CONFIG_ACPI
290 285
291int cpe_vector = -1; 286int cpe_vector = -1;
@@ -378,8 +373,6 @@ ia64_mca_register_cpev (int cpev)
378} 373}
379#endif /* CONFIG_ACPI */ 374#endif /* CONFIG_ACPI */
380 375
381#endif /* PLATFORM_MCA_HANDLERS */
382
383/* 376/*
384 * ia64_mca_cmc_vector_setup 377 * ia64_mca_cmc_vector_setup
385 * 378 *
@@ -631,6 +624,32 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
631 *tnat |= (nat << tslot); 624 *tnat |= (nat << tslot);
632} 625}
633 626
627/* Change the comm field on the MCA/INT task to include the pid that
628 * was interrupted, it makes for easier debugging. If that pid was 0
629 * (swapper or nested MCA/INIT) then use the start of the previous comm
630 * field suffixed with its cpu.
631 */
632
633static void
634ia64_mca_modify_comm(const task_t *previous_current)
635{
636 char *p, comm[sizeof(current->comm)];
637 if (previous_current->pid)
638 snprintf(comm, sizeof(comm), "%s %d",
639 current->comm, previous_current->pid);
640 else {
641 int l;
642 if ((p = strchr(previous_current->comm, ' ')))
643 l = p - previous_current->comm;
644 else
645 l = strlen(previous_current->comm);
646 snprintf(comm, sizeof(comm), "%s %*s %d",
647 current->comm, l, previous_current->comm,
648 task_thread_info(previous_current)->cpu);
649 }
650 memcpy(current->comm, comm, sizeof(current->comm));
651}
652
634/* On entry to this routine, we are running on the per cpu stack, see 653/* On entry to this routine, we are running on the per cpu stack, see
635 * mca_asm.h. The original stack has not been touched by this event. Some of 654 * mca_asm.h. The original stack has not been touched by this event. Some of
636 * the original stack's registers will be in the RBS on this stack. This stack 655 * the original stack's registers will be in the RBS on this stack. This stack
@@ -649,7 +668,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
649 struct ia64_sal_os_state *sos, 668 struct ia64_sal_os_state *sos,
650 const char *type) 669 const char *type)
651{ 670{
652 char *p, comm[sizeof(current->comm)]; 671 char *p;
653 ia64_va va; 672 ia64_va va;
654 extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ 673 extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */
655 const pal_min_state_area_t *ms = sos->pal_min_state; 674 const pal_min_state_area_t *ms = sos->pal_min_state;
@@ -722,6 +741,10 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
722 /* Verify the previous stack state before we change it */ 741 /* Verify the previous stack state before we change it */
723 if (user_mode(regs)) { 742 if (user_mode(regs)) {
724 msg = "occurred in user space"; 743 msg = "occurred in user space";
744 /* previous_current is guaranteed to be valid when the task was
745 * in user space, so ...
746 */
747 ia64_mca_modify_comm(previous_current);
725 goto no_mod; 748 goto no_mod;
726 } 749 }
727 if (r13 != sos->prev_IA64_KR_CURRENT) { 750 if (r13 != sos->prev_IA64_KR_CURRENT) {
@@ -751,25 +774,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
751 goto no_mod; 774 goto no_mod;
752 } 775 }
753 776
754 /* Change the comm field on the MCA/INT task to include the pid that 777 ia64_mca_modify_comm(previous_current);
755 * was interrupted, it makes for easier debugging. If that pid was 0
756 * (swapper or nested MCA/INIT) then use the start of the previous comm
757 * field suffixed with its cpu.
758 */
759 if (previous_current->pid)
760 snprintf(comm, sizeof(comm), "%s %d",
761 current->comm, previous_current->pid);
762 else {
763 int l;
764 if ((p = strchr(previous_current->comm, ' ')))
765 l = p - previous_current->comm;
766 else
767 l = strlen(previous_current->comm);
768 snprintf(comm, sizeof(comm), "%s %*s %d",
769 current->comm, l, previous_current->comm,
770 task_thread_info(previous_current)->cpu);
771 }
772 memcpy(current->comm, comm, sizeof(current->comm));
773 778
774 /* Make the original task look blocked. First stack a struct pt_regs, 779 /* Make the original task look blocked. First stack a struct pt_regs,
775 * describing the state at the time of interrupt. mca_asm.S built a 780 * describing the state at the time of interrupt. mca_asm.S built a
@@ -909,7 +914,7 @@ no_mod:
909static void 914static void
910ia64_wait_for_slaves(int monarch) 915ia64_wait_for_slaves(int monarch)
911{ 916{
912 int c, wait = 0; 917 int c, wait = 0, missing = 0;
913 for_each_online_cpu(c) { 918 for_each_online_cpu(c) {
914 if (c == monarch) 919 if (c == monarch)
915 continue; 920 continue;
@@ -920,15 +925,32 @@ ia64_wait_for_slaves(int monarch)
920 } 925 }
921 } 926 }
922 if (!wait) 927 if (!wait)
923 return; 928 goto all_in;
924 for_each_online_cpu(c) { 929 for_each_online_cpu(c) {
925 if (c == monarch) 930 if (c == monarch)
926 continue; 931 continue;
927 if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { 932 if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
928 udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */ 933 udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */
934 if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
935 missing = 1;
929 break; 936 break;
930 } 937 }
931 } 938 }
939 if (!missing)
940 goto all_in;
941 printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
942 for_each_online_cpu(c) {
943 if (c == monarch)
944 continue;
945 if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
946 printk(" %d", c);
947 }
948 printk("\n");
949 return;
950
951all_in:
952 printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
953 return;
932} 954}
933 955
934/* 956/*
@@ -954,6 +976,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
954 task_t *previous_current; 976 task_t *previous_current;
955 977
956 oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ 978 oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
979 console_loglevel = 15; /* make sure printks make it to console */
980 printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
981 sos->proc_state_param, cpu, sos->monarch);
982
957 previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); 983 previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
958 monarch_cpu = cpu; 984 monarch_cpu = cpu;
959 if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) 985 if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)