11 #include <linux/types.h>
13 #include <linux/sched.h>
20 #include <linux/module.h>
21 #include <linux/kernel.h>
25 #include <linux/slab.h>
27 #include <asm/delay.h>
28 #include <asm/machvec.h>
30 #include <asm/ptrace.h>
35 #include <asm/hw_irq.h>
40 static int sal_rec_max = 10000;
52 #define MAX_PAGE_ISOLATE 1024
55 static int num_page_isolate = 0;
78 fatal_mca(
const char *
fmt, ...)
92 mca_recovered(
const char *
fmt, ...)
114 mca_page_isolate(
unsigned long paddr)
120 if (!ia64_phys_addr_valid(paddr))
130 for (i = 0; i < num_page_isolate; i++)
131 if (page_isolate[i] == p)
139 if (PageSlab(p) || PageReserved(p))
145 page_isolate[num_page_isolate++] =
p;
160 "iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
163 iip, ipsr, paddr,
current->comm);
165 spin_lock(&mca_bh_lock);
166 switch (mca_page_isolate(paddr)) {
176 spin_unlock(&mca_bh_lock);
195 u64 total_check_num = slpi->
valid.num_cache_check
196 + slpi->
valid.num_tlb_check
197 + slpi->
valid.num_bus_check
198 + slpi->
valid.num_reg_file_check
199 + slpi->
valid.num_ms_check;
206 (slpi->
valid.cpuid_info ? ((
char*)slpi + head_size) :
NULL);
208 (slpi->
valid.psi_static_struct ?
209 ((
char*)slpi + head_size + mid_size) :
NULL);
220 #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
221 {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
223 list_add(&hl->list, &(sect)); \
224 slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
229 int platform_err = 0;
259 ercd_pos < record_len; ercd_pos += sp->
len, sects++) {
263 }
else if (!efi_guidcmp(sp->
guid,
267 }
else if (!efi_guidcmp(sp->
guid,
271 }
else if (!efi_guidcmp(sp->
guid,
275 }
else if (!efi_guidcmp(sp->
guid,
279 }
else if (!efi_guidcmp(sp->
guid,
283 }
else if (!efi_guidcmp(sp->
guid,
287 }
else if (!efi_guidcmp(sp->
guid,
291 }
else if (!efi_guidcmp(sp->
guid,
311 init_record_index_pools(
void)
317 static int sal_log_sect_min_sizes[] = {
342 rec_max_size = sal_rec_max;
345 sect_min_size = sal_log_sect_min_sizes[0];
346 for (i = 1; i <
sizeof sal_log_sect_min_sizes/
sizeof(
size_t); i++)
347 if (sect_min_size > sal_log_sect_min_sizes[i])
348 sect_min_size = sal_log_sect_min_sizes[
i];
351 slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
355 return slidx_pool.buffer ? 0 : -
ENOMEM;
387 switch (sos->
rv_rc) {
402 if (psp->
tc || psp->
cc || psp->
rc || psp->
uc)
409 if (!pbci || pbci->
ib)
447 u64 target_address = 0;
461 if (!target_address || (pcci->
level < level)) {
469 return target_address;
475 if (smei && smei->
valid.target_identifier)
497 u64 target_identifier;
503 target_identifier = get_target_identifier(peidx);
504 if (!target_identifier)
505 return fatal_mca(
"target address not valid");
523 return fatal_mca(
"minstate not valid");
533 if (psr1->
cpl != 0 ||
540 pmsa->
pmsa_gr[8-1] = target_identifier;
555 return mca_recovered(
"user memory corruption. "
556 "kill affected process - recovered.");
559 return fatal_mca(
"kernel context not recovered, iip 0x%lx\n",
583 if (psp->
bc && pbci->
eb && pbci->
bsi == 0) {
588 status = recover_from_read_error(slidx, peidx, pbci,
605 }
else if (psp->
cc && !psp->
bc) {
606 status = recover_from_read_error(slidx, peidx, pbci, sos);
633 && !(ptci->
itr || ptci->
dtc || ptci->
itc))
634 return fatal_mca(
"Duplicate TLB entry");
636 return mca_recovered(
"TLB check recovered");
652 recover_from_processor_error(
int platform,
slidx_table_t *slidx,
668 return mca_recovered(
"machine check is already corrected.");
673 if (psp->
us || psp->
ci == 0)
674 return fatal_mca(
"error not contained");
679 if (psp->
tc && !(psp->
cc || psp->
bc || psp->
rc || psp->
uc))
680 return recover_from_tlb_check(peidx);
690 if (psp->
cc == 0 && (psp->
bc == 0 || pbci ==
NULL))
691 return fatal_mca(
"No cache or bus check");
697 return fatal_mca(
"Too many bus checks");
700 return fatal_mca(
"Internal Bus error");
701 if (pbci->
eb && pbci->
bsi > 0)
702 return fatal_mca(
"External bus check fatal status");
708 return recover_from_platform_error(slidx, peidx, pbci, sos);
713 return fatal_mca(
"Strange SAL record");
735 platform_err = mca_make_slidx(rec, &slidx);
742 return fatal_mca(
"Too Many Errors");
743 else if (n_proc_err == 0)
745 return fatal_mca(
"Weird SAL record");
755 if (is_mca_global(&peidx, &pbci, sos))
756 return fatal_mca(
"global MCA");
759 return recover_from_processor_error(platform_err, &slidx, &peidx,
769 if (init_record_index_pools())
775 kfree(slidx_pool.buffer);
785 kfree(slidx_pool.buffer);