Loading arch/arc/include/asm/mmu.h +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ typedef struct { } mm_context_t; #ifdef CONFIG_ARC_DBG_TLB_PARANOIA void tlb_paranoid_check(unsigned int pid_sw, unsigned long address); void tlb_paranoid_check(unsigned int mm_asid, unsigned long address); #else #define tlb_paranoid_check(a, b) #endif Loading arch/arc/mm/tlb.c +13 −11 Original line number Diff line number Diff line Loading @@ -688,25 +688,27 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, * Low Level ASM TLB handler calls this if it finds that HW and SW ASIDS * don't match */ void print_asid_mismatch(int is_fast_path) void print_asid_mismatch(int mm_asid, int mmu_asid, int is_fast_path) { int pid_sw, pid_hw; pid_sw = current->active_mm->context.asid; pid_hw = read_aux_reg(ARC_REG_PID) & 0xff; pr_emerg("ASID Mismatch in %s Path Handler: sw-pid=0x%x hw-pid=0x%x\n", is_fast_path ? "Fast" : "Slow", pid_sw, pid_hw); is_fast_path ? "Fast" : "Slow", mm_asid, mmu_asid); __asm__ __volatile__("flag 1"); } void tlb_paranoid_check(unsigned int pid_sw, unsigned long addr) void tlb_paranoid_check(unsigned int mm_asid, unsigned long addr) { unsigned int pid_hw; unsigned int mmu_asid; pid_hw = read_aux_reg(ARC_REG_PID) & 0xff; mmu_asid = read_aux_reg(ARC_REG_PID) & 0xff; if (addr < 0x70000000 && ((pid_hw != pid_sw) || (pid_sw == NO_ASID))) print_asid_mismatch(0); /* * At the time of a TLB miss/installation * - HW version needs to match SW version * - SW needs to have a valid ASID */ if (addr < 0x70000000 && ((mmu_asid != mm_asid) || (mm_asid == NO_ASID))) print_asid_mismatch(mm_asid, mmu_asid, 0); } #endif arch/arc/mm/tlbex.S +7 −9 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ ex_saved_reg1: ; VERIFY if the ASID in MMU-PID Reg is same as ; one in Linux data structures DBG_ASID_MISMATCH tlb_paranoid_check_asm .endm .macro TLBMISS_RESTORE_REGS Loading Loading @@ -133,31 +133,29 @@ ex_saved_reg1: ; In bizzare scenrios SW and HW ASID can get out-of-sync which is trouble. ; So we try to detect this in TLB Mis shandler .macro DBG_ASID_MISMATCH .macro tlb_paranoid_check_asm #ifdef CONFIG_ARC_DBG_TLB_PARANOIA ; make sure h/w ASID is same as s/w ASID GET_CURR_TASK_ON_CPU r3 ld r0, [r3, TASK_ACT_MM] ld r0, [r0, MM_CTXT+MM_CTXT_ASID] lr r1, [ARC_REG_PID] and r1, r1, 0xFF breq r1, r0, 5f ; Error if H/w and S/w ASID don't match, but NOT if in kernel mode lr r0, [erstatus] bbit0 r0, STATUS_U_BIT, 5f lr r2, [erstatus] bbit0 r2, STATUS_U_BIT, 5f ; We sure are in troubled waters, Flag the error, but to do so ; need to switch to kernel mode stack to call error routine GET_TSK_STACK_BASE r3, sp ; Call printk to shoutout aloud mov r0, 1 mov r2, 1 j print_asid_mismatch 5: ; ASIDs match so proceed normally Loading Loading
arch/arc/include/asm/mmu.h +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ typedef struct { } mm_context_t; #ifdef CONFIG_ARC_DBG_TLB_PARANOIA void tlb_paranoid_check(unsigned int pid_sw, unsigned long address); void tlb_paranoid_check(unsigned int mm_asid, unsigned long address); #else #define tlb_paranoid_check(a, b) #endif Loading
arch/arc/mm/tlb.c +13 −11 Original line number Diff line number Diff line Loading @@ -688,25 +688,27 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, * Low Level ASM TLB handler calls this if it finds that HW and SW ASIDS * don't match */ void print_asid_mismatch(int is_fast_path) void print_asid_mismatch(int mm_asid, int mmu_asid, int is_fast_path) { int pid_sw, pid_hw; pid_sw = current->active_mm->context.asid; pid_hw = read_aux_reg(ARC_REG_PID) & 0xff; pr_emerg("ASID Mismatch in %s Path Handler: sw-pid=0x%x hw-pid=0x%x\n", is_fast_path ? "Fast" : "Slow", pid_sw, pid_hw); is_fast_path ? "Fast" : "Slow", mm_asid, mmu_asid); __asm__ __volatile__("flag 1"); } void tlb_paranoid_check(unsigned int pid_sw, unsigned long addr) void tlb_paranoid_check(unsigned int mm_asid, unsigned long addr) { unsigned int pid_hw; unsigned int mmu_asid; pid_hw = read_aux_reg(ARC_REG_PID) & 0xff; mmu_asid = read_aux_reg(ARC_REG_PID) & 0xff; if (addr < 0x70000000 && ((pid_hw != pid_sw) || (pid_sw == NO_ASID))) print_asid_mismatch(0); /* * At the time of a TLB miss/installation * - HW version needs to match SW version * - SW needs to have a valid ASID */ if (addr < 0x70000000 && ((mmu_asid != mm_asid) || (mm_asid == NO_ASID))) print_asid_mismatch(mm_asid, mmu_asid, 0); } #endif
arch/arc/mm/tlbex.S +7 −9 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ ex_saved_reg1: ; VERIFY if the ASID in MMU-PID Reg is same as ; one in Linux data structures DBG_ASID_MISMATCH tlb_paranoid_check_asm .endm .macro TLBMISS_RESTORE_REGS Loading Loading @@ -133,31 +133,29 @@ ex_saved_reg1: ; In bizzare scenrios SW and HW ASID can get out-of-sync which is trouble. ; So we try to detect this in TLB Mis shandler .macro DBG_ASID_MISMATCH .macro tlb_paranoid_check_asm #ifdef CONFIG_ARC_DBG_TLB_PARANOIA ; make sure h/w ASID is same as s/w ASID GET_CURR_TASK_ON_CPU r3 ld r0, [r3, TASK_ACT_MM] ld r0, [r0, MM_CTXT+MM_CTXT_ASID] lr r1, [ARC_REG_PID] and r1, r1, 0xFF breq r1, r0, 5f ; Error if H/w and S/w ASID don't match, but NOT if in kernel mode lr r0, [erstatus] bbit0 r0, STATUS_U_BIT, 5f lr r2, [erstatus] bbit0 r2, STATUS_U_BIT, 5f ; We sure are in troubled waters, Flag the error, but to do so ; need to switch to kernel mode stack to call error routine GET_TSK_STACK_BASE r3, sp ; Call printk to shoutout aloud mov r0, 1 mov r2, 1 j print_asid_mismatch 5: ; ASIDs match so proceed normally Loading