MCA/TLB recovery
PATCH 1/1 MCA/TLB recovery
Here's all the rest. Code to save enough information about the settings in the ITR/DTR registers in an array of structures (ia64_mca_tlb_list[]). Then when an MCA comes we check the "processor state parameter" to see if this was a TLB error, if so we purge the whole TC, and all the ITR/DTR registers and reload the ITR/DTR registers in physical mode in mca_asm.S. Note that we use cr.lid to identify the right entry in the array, because in physical mode we can't tell which linux logical cpu number we are (smp_processor_id() can't be called).
C-code in mca.c now uses the same min_state area that the PAL used, and checks to see if the error was just a TLB error, in which case everything was fixed, and we can ask the SAL to continue. Otherwise we still reboot.
Acknowledgements:
most of this piece of the patch was written by Fenghua Yu based on earlier versions by Jenna Hall, and by me.
-Tony
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"
@@ -186,4 +187,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
@@ -402,6 +403,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;
@@ -460,6 +464,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 -122
442 lines not on this page · raw message
arch/ia64/kernel/mca.c +20 -33
106 lines not on this page · raw message
arch/ia64/mm/init.c +22 -0
@@ -32,6 +32,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);
@@ -327,6 +328,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
@@ -385,6 +390,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_asm.h +1 -1
@@ -113,7 +113,7 @@movl temp2 = start_addr; \ mov cr.ipsr = temp1; \ ;; \ -INST_VA_TO_PA (temp2); \ +LOAD_PHYSICAL (p0,temp2,start_addr); \ ;; \ mov cr.iip = temp2; \ mov cr.ifs = r0; \
include/asm-ia64/mca.h +13 -1
@@ -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;
@@ -108,7 +120,7 @@IA64_MCA_NEW_CONTEXT =-1 /* SAL to return to new context */ }; -#define MIN_STATE_AREA_SIZE 57 +#define MIN_STATE_AREA_SIZE 58 typedef struct ia64_mca_os_to_sal_state_s { u64 imots_os_status; /* OS status to SAL as to what happened
include/asm-ia64/pal.h +7 -5
@@ -405,10 +405,11 @@* generated. * (Trap Lost ) */ - op :3 ,/* Operation that -* caused the machine -* check + mi : 1, /* More information available + * call PAL_MC_ERROR_INFO */ + pi : 1, /* Precise instruction pointer */ + pm : 1, /* Precise min-state save area */ dy : 1, /* Processor dynamic* state valid
@@ -450,11 +451,12 @@* by the processor */ - reserved2 : 12, + reserved2 : 11, cc : 1, /* Cache check */ tc : 1, /* TLB check */ bc : 1, /* Bus check */ - uc : 1; /* Unknown check */ + rc : 1, /* Register file check */ + uc : 1; /* Uarch check */ } pal_processor_state_info_t;
include/asm-ia64/pgtable.h +4 -0
@@ -232,6 +232,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)))