2.6.0 MCA TLB error recovery
PATCH 1/1 2.6.0 MCA TLB error recovery
David,
Here's the updated version of the MCA TLB recovery patch (and I've made the assumption that you'll take Keith's salinfo patch from 11/25 and the deadlock fix that he posted on 12/7 first ... so this patch is against base 2.6.0 with Keith's patches applied).
One slight glitch that I don't understand. When I injected a TLB error I saw this printk on the console:
+CPU 3: SAL log contains MCA error record
+Err Record ID: 545586543104884737 SAL Rev: 0.03
+Time: 12/18/2003 10:28:32 Severity 0
But the salinfo_decode daemon didn't wake up to pluck this from the kernel and deposit it in /var/log/salinfo/{raw,decoded}/* After I rebooted the daemon picked up the log and decoded it and reported 4 copies of the same stuff, one from each cpu:
BEGIN HARDWARE ERROR STATE from mca on cpu 3
Err Record ID: 545586543104884737 SAL Rev: 0.03
Time: 2003-12-18 10:28:32 Severity 0
Processor Device Error Info Section
UNCORRECTED PROCESSOR ERROR: TLB Check
processor lid : 0x00000000c6180000
cpu: M nasid: 0x618
processor state parameter: 0x10000000ff7211a0blah, blah, blah
It looks like salinfo_log_wakeup() is called right before ia64_log_print() ... so I'm not sure why the salinfo_decode daemon kept on snoozing. Keith: am I missing something obvious?
Here's the patch (substantial portions of this code written by Fenghua Yu):
arch/ia64/kernel/asm-offsets.c +4 -0
@@ -12,6 +12,7 @@#include <asm-ia64/ptrace.h> #include <asm-ia64/siginfo.h> #include <asm-ia64/sigcontext.h> +#include <asm-ia64/mca.h> #include "../kernel/sigframe.h"
@@ -204,4 +205,7 @@# error "CLONE_SETTLS_BIT incorrect, please fix"#endif +BLANK (); +DEFINE (IA64_MCA_TLB_INFO_SIZE ,sizeof (struct ia64_mca_tlb_info )); + }
arch/ia64/kernel/efi.c +12 -0
@@ -30,6 +30,7 @@#include <asm/kregs.h> #include <asm/pgtable.h> #include <asm/processor.h> +#include <asm/mca.h> #define EFI_DEBUG 0
@@ -395,6 +396,9 @@int pal_code_count =0 ;u64 mask, psr;u64 vaddr; +#ifdef CONFIG_IA64_MCA +int cpu; +#endif efi_map_start =__va (ia64_boot_param->efi_memmap); efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -455,6 +459,14 @@ IA64_GRANULE_SHIFT);ia64_set_psr (psr);/* restore psr */ ia64_srlz_i (); + +#ifdef CONFIG_IA64_MCA + cpu =smp_processor_id (); + +/* insert this TR into our list for MCA recovery purposes */ + ia64_mca_tlb_list[cpu].pal_base=vaddr & mask; + ia64_mca_tlb_list[cpu].pal_paddr=pte_val (mk_pte_phys (md->phys_addr,PAGE_KERNEL )); +#endif } }
arch/ia64/kernel/mca_asm.S +237 -120
440 lines not on this page · raw message
arch/ia64/kernel/mca.c +18 -6
@@ -78,9 +78,8 @@u64 ia64_mca_stackframe[32 ];u64 ia64_mca_bspstore[1024 ]; u64 ia64_init_stack[KERNEL_STACK_SIZE/8] __attribute__((aligned(16))); -u64 ia64_mca_sal_data_area[1356 ]; -u64 ia64_tlb_functional;u64 ia64_os_mca_recovery_successful; +u64 ia64_mca_serialize;static void ia64_mca_wakeup_ipi_wait (void );static void ia64_mca_wakeup (int cpu);static void ia64_mca_wakeup_all (void );
@@ -90,6 +89,8 @@static u64 ia64_log_get (int sal_info_type,u8 **buffer);extern struct hw_interrupt_type irq_type_iosapic_level; +struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS ]; +static struct irqaction cmci_irqaction = { .handler = ia64_mca_cmc_int_handler, .flags =SA_INTERRUPT ,
@@ -944,6 +945,9 @@void ia64_return_to_sal_check (void ) { +pal_processor_state_info_t *psp = (pal_processor_state_info_t *) + &ia64_sal_to_os_handoff_state.proc_state_param; +/* Copy over some relevant stuff from the sal_to_os_mca_handoff * so that it can be used at the time of os_mca_to_sal_handoff */
@@ -953,14 +957,22 @@ ia64_os_to_sal_handoff_state.imots_sal_check_ra ia64_sal_to_os_handoff_state.imsto_sal_check_ra; -/* Cold Boot for uncorrectable MCA */ - ia64_os_to_sal_handoff_state.imots_os_status =IA64_MCA_COLD_BOOT ; +/* +* Did we correct the error? At the moment the only error that +* we fix is a TLB error, if any other kind of error occurred +* we must reboot. +*/ +if (psp->cc =1 && psp->bc =1 && psp->rc =1 && psp->uc =1 ) + ia64_os_to_sal_handoff_state.imots_os_status =IA64_MCA_COLD_BOOT ; +else + ia64_os_to_sal_handoff_state.imots_os_status =IA64_MCA_CORRECTED ;/* Default = tell SAL to return to same context */ ia64_os_to_sal_handoff_state.imots_context =IA64_MCA_SAME_CONTEXT ; ia64_os_to_sal_handoff_state.imots_new_min_state (u64 *)ia64_sal_to_os_handoff_state.pal_min_state; + }/*
@@ -1338,8 +1350,8 @@void ia64_log_prt_guid (efi_guid_t *p_guid,prfunc_t prfunc) { -char out[40 ]; -printk (KERN_DEBUG "GUID = %s\n" ,efi_guid_unparse (p_guid, out)); +//char out[40]; +//printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out)); } static void
arch/ia64/mm/init.c +22 -0
@@ -34,6 +34,7 @@#include <asm/tlb.h> #include <asm/uaccess.h> #include <asm/unistd.h> +#include <asm/mca.h> DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -277,6 +278,10 @@ {unsigned long psr, pta, impl_va_bits;extern void __init tlb_init (void ); +#ifdef CONFIG_IA64_MCA +int cpu; +#endif +#ifdef CONFIG_DISABLE_VHPT # define VHPT_ENABLE_BIT 0#else
@@ -335,6 +340,23 @@ia64_set_pta (pta | (0 <<8 ) | (vmlpt_bits <<2 ) |VHPT_ENABLE_BIT );ia64_tlb_init (); + +#ifdef CONFIG_IA64_MCA + cpu =smp_processor_id (); + +/* mca handler uses cr.lid as key to pick the right entry */ + ia64_mca_tlb_list[cpu].cr_lid =ia64_getreg (_IA64_REG_CR_LID); + +/* insert this percpu data information into our list for MCA recovery purposes */ + ia64_mca_tlb_list[cpu].percpu_paddr=pte_val (mk_pte_phys (__pa (my_cpu_data),PAGE_KERNEL )); +/* Also save per-cpu tlb flush recipe for use in physical mode mca handler */ + ia64_mca_tlb_list[cpu].ptce_base=local_cpu_data->ptce_base; + ia64_mca_tlb_list[cpu].ptce_count[0 ]=local_cpu_data->ptce_count[0 ]; + ia64_mca_tlb_list[cpu].ptce_count[1 ]=local_cpu_data->ptce_count[1 ]; + ia64_mca_tlb_list[cpu].ptce_stride[0 ]=local_cpu_data->ptce_stride[0 ]; + ia64_mca_tlb_list[cpu].ptce_stride[1 ]=local_cpu_data->ptce_stride[1 ]; +#endif + }#ifdef CONFIG_VIRTUAL_MEM_MAP
include/asm-ia64/mca.h +12 -0
@@ -18,6 +18,7 @@#include <asm/param.h> #include <asm/sal.h> #include <asm/processor.h> +#include <asm/mca_asm.h> /* These are the return codes from all the IA64_MCA specific interfaces */ typedef int ia64_mca_return_code_t ;
@@ -61,6 +62,17 @@IA64_MCA_RENDEZ_CHECKIN_DONE =0x1 }; +/* the following data structure is used for TLB error recovery purposes */ +extern struct ia64_mca_tlb_info { +u64 cr_lid; +u64 percpu_paddr; +u64 ptce_base; +u32 ptce_count[2 ]; +u32 ptce_stride[2 ]; +u64 pal_paddr; +u64 pal_base; +} ia64_mca_tlb_list[NR_CPUS ]; +/* Information maintained by the MC infrastructure */ typedef struct ia64_mc_info_s { u64 imi_mca_handler;
include/asm-ia64/pgtable.h +4 -0
@@ -230,6 +230,10 @@#define mk_pte (page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) +/* This takes a physical page address that is used by the remapping functions */ +#define mk_pte_phys (physpage, pgprot) \ +({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; }) +#define pte_modify (_pte, newprot) \ (__pte((pte_val(_pte) & ~_PAGE_CHG_MASK) | (pgprot_val(newprot) & _PAGE_CHG_MASK)))