Skip to contentSkip to conversation

MCA/TLB recovery

PATCH New Luck, Tony 1 participant 1 message Oct 3, 2003 EFI

lore
Share & tools
lore

Luck, Tony

author
#0 lore raw

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
diff -ru temp/arch/ia64/kernel/asm-offsets.c mca/arch/ia64/kernel/asm-offsets.c
@@ -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
diff -ru temp/arch/ia64/kernel/efi.c mca/arch/ia64/kernel/efi.c
@@ -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
diff -ru temp/arch/ia64/mm/init.c mca/arch/ia64/mm/init.c
@@ -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
diff -ru temp/include/asm-ia64/mca_asm.h mca/include/asm-ia64/mca_asm.h
@@ -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
diff -ru temp/include/asm-ia64/mca.h mca/include/asm-ia64/mca.h
@@ -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
diff -ru temp/include/asm-ia64/pal.h mca/include/asm-ia64/pal.h
@@ -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
diff -ru temp/include/asm-ia64/pgtable.h mca/include/asm-ia64/pgtable.h
@@ -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)))