Commit dc5cdd8e authored by Tony Luck's avatar Tony Luck

Pull mca-cleanup into release branch

parents ae02e964 2730c929
...@@ -281,11 +281,6 @@ ia64_mca_log_sal_error_record(int sal_info_type) ...@@ -281,11 +281,6 @@ ia64_mca_log_sal_error_record(int sal_info_type)
ia64_sal_clear_state_info(sal_info_type); ia64_sal_clear_state_info(sal_info_type);
} }
/*
* platform dependent error handling
*/
#ifndef PLATFORM_MCA_HANDLERS
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
int cpe_vector = -1; int cpe_vector = -1;
...@@ -378,8 +373,6 @@ ia64_mca_register_cpev (int cpev) ...@@ -378,8 +373,6 @@ ia64_mca_register_cpev (int cpev)
} }
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
#endif /* PLATFORM_MCA_HANDLERS */
/* /*
* ia64_mca_cmc_vector_setup * ia64_mca_cmc_vector_setup
* *
...@@ -631,6 +624,32 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat) ...@@ -631,6 +624,32 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
*tnat |= (nat << tslot); *tnat |= (nat << tslot);
} }
/* Change the comm field on the MCA/INT task to include the pid that
* was interrupted, it makes for easier debugging. If that pid was 0
* (swapper or nested MCA/INIT) then use the start of the previous comm
* field suffixed with its cpu.
*/
static void
ia64_mca_modify_comm(const task_t *previous_current)
{
char *p, comm[sizeof(current->comm)];
if (previous_current->pid)
snprintf(comm, sizeof(comm), "%s %d",
current->comm, previous_current->pid);
else {
int l;
if ((p = strchr(previous_current->comm, ' ')))
l = p - previous_current->comm;
else
l = strlen(previous_current->comm);
snprintf(comm, sizeof(comm), "%s %*s %d",
current->comm, l, previous_current->comm,
task_thread_info(previous_current)->cpu);
}
memcpy(current->comm, comm, sizeof(current->comm));
}
/* On entry to this routine, we are running on the per cpu stack, see /* On entry to this routine, we are running on the per cpu stack, see
* mca_asm.h. The original stack has not been touched by this event. Some of * mca_asm.h. The original stack has not been touched by this event. Some of
* the original stack's registers will be in the RBS on this stack. This stack * 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,7 +668,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
struct ia64_sal_os_state *sos, struct ia64_sal_os_state *sos,
const char *type) const char *type)
{ {
char *p, comm[sizeof(current->comm)]; char *p;
ia64_va va; ia64_va va;
extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */
const pal_min_state_area_t *ms = sos->pal_min_state; 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,6 +741,10 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
/* Verify the previous stack state before we change it */ /* Verify the previous stack state before we change it */
if (user_mode(regs)) { if (user_mode(regs)) {
msg = "occurred in user space"; msg = "occurred in user space";
/* previous_current is guaranteed to be valid when the task was
* in user space, so ...
*/
ia64_mca_modify_comm(previous_current);
goto no_mod; goto no_mod;
} }
if (r13 != sos->prev_IA64_KR_CURRENT) { if (r13 != sos->prev_IA64_KR_CURRENT) {
...@@ -751,25 +774,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, ...@@ -751,25 +774,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
goto no_mod; goto no_mod;
} }
/* Change the comm field on the MCA/INT task to include the pid that ia64_mca_modify_comm(previous_current);
* was interrupted, it makes for easier debugging. If that pid was 0
* (swapper or nested MCA/INIT) then use the start of the previous comm
* field suffixed with its cpu.
*/
if (previous_current->pid)
snprintf(comm, sizeof(comm), "%s %d",
current->comm, previous_current->pid);
else {
int l;
if ((p = strchr(previous_current->comm, ' ')))
l = p - previous_current->comm;
else
l = strlen(previous_current->comm);
snprintf(comm, sizeof(comm), "%s %*s %d",
current->comm, l, previous_current->comm,
task_thread_info(previous_current)->cpu);
}
memcpy(current->comm, comm, sizeof(current->comm));
/* Make the original task look blocked. First stack a struct pt_regs, /* Make the original task look blocked. First stack a struct pt_regs,
* describing the state at the time of interrupt. mca_asm.S built a * describing the state at the time of interrupt. mca_asm.S built a
...@@ -909,7 +914,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, ...@@ -909,7 +914,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
static void static void
ia64_wait_for_slaves(int monarch) ia64_wait_for_slaves(int monarch)
{ {
int c, wait = 0; int c, wait = 0, missing = 0;
for_each_online_cpu(c) { for_each_online_cpu(c) {
if (c == monarch) if (c == monarch)
continue; continue;
...@@ -920,15 +925,32 @@ ia64_wait_for_slaves(int monarch) ...@@ -920,15 +925,32 @@ ia64_wait_for_slaves(int monarch)
} }
} }
if (!wait) if (!wait)
return; goto all_in;
for_each_online_cpu(c) { for_each_online_cpu(c) {
if (c == monarch) if (c == monarch)
continue; continue;
if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */ udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */
if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
missing = 1;
break; break;
} }
} }
if (!missing)
goto all_in;
printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
for_each_online_cpu(c) {
if (c == monarch)
continue;
if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
printk(" %d", c);
}
printk("\n");
return;
all_in:
printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
return;
} }
/* /*
...@@ -954,6 +976,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, ...@@ -954,6 +976,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
task_t *previous_current; task_t *previous_current;
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
console_loglevel = 15; /* make sure printks make it to console */
printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
sos->proc_state_param, cpu, sos->monarch);
previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
monarch_cpu = cpu; monarch_cpu = cpu;
if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment