162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * TLB Exception Handling for ARC 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Vineetg: April 2011 : 862306a36Sopenharmony_ci * -MMU v1: moved out legacy code into a seperate file 962306a36Sopenharmony_ci * -MMU v3: PD{0,1} bits layout changed: They don't overlap anymore, 1062306a36Sopenharmony_ci * helps avoid a shift when preparing PD0 from PTE 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Vineetg: July 2009 1362306a36Sopenharmony_ci * -For MMU V2, we need not do heuristics at the time of commiting a D-TLB 1462306a36Sopenharmony_ci * entry, so that it doesn't knock out it's I-TLB entry 1562306a36Sopenharmony_ci * -Some more fine tuning: 1662306a36Sopenharmony_ci * bmsk instead of add, asl.cc instead of branch, delay slot utilise etc 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Vineetg: July 2009 1962306a36Sopenharmony_ci * -Practically rewrote the I/D TLB Miss handlers 2062306a36Sopenharmony_ci * Now 40 and 135 instructions a peice as compared to 131 and 449 resp. 2162306a36Sopenharmony_ci * Hence Leaner by 1.5 K 2262306a36Sopenharmony_ci * Used Conditional arithmetic to replace excessive branching 2362306a36Sopenharmony_ci * Also used short instructions wherever possible 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Vineetg: Aug 13th 2008 2662306a36Sopenharmony_ci * -Passing ECR (Exception Cause REG) to do_page_fault( ) for printing 2762306a36Sopenharmony_ci * more information in case of a Fatality 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Vineetg: March 25th Bug #92690 3062306a36Sopenharmony_ci * -Added Debug Code to check if sw-ASID == hw-ASID 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci * Rahul Trivedi, Amit Bhor: Codito Technologies 2004 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <linux/linkage.h> 3662306a36Sopenharmony_ci#include <linux/pgtable.h> 3762306a36Sopenharmony_ci#include <asm/entry.h> 3862306a36Sopenharmony_ci#include <asm/mmu.h> 3962306a36Sopenharmony_ci#include <asm/arcregs.h> 4062306a36Sopenharmony_ci#include <asm/cache.h> 4162306a36Sopenharmony_ci#include <asm/processor.h> 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#ifdef CONFIG_ISA_ARCOMPACT 4462306a36Sopenharmony_ci;----------------------------------------------------------------- 4562306a36Sopenharmony_ci; ARC700 Exception Handling doesn't auto-switch stack and it only provides 4662306a36Sopenharmony_ci; ONE scratch AUX reg "ARC_REG_SCRATCH_DATA0" 4762306a36Sopenharmony_ci; 4862306a36Sopenharmony_ci; For Non-SMP, the scratch AUX reg is repurposed to cache task PGD, so a 4962306a36Sopenharmony_ci; "global" is used to free-up FIRST core reg to be able to code the rest of 5062306a36Sopenharmony_ci; exception prologue (IRQ auto-disabled on Exceptions, so it's IRQ-safe). 5162306a36Sopenharmony_ci; Since the Fast Path TLB Miss handler is coded with 4 regs, the remaining 3 5262306a36Sopenharmony_ci; need to be saved as well by extending the "global" to be 4 words. Hence 5362306a36Sopenharmony_ci; ".size ex_saved_reg1, 16" 5462306a36Sopenharmony_ci; [All of this dance is to avoid stack switching for each TLB Miss, since we 5562306a36Sopenharmony_ci; only need to save only a handful of regs, as opposed to complete reg file] 5662306a36Sopenharmony_ci; 5762306a36Sopenharmony_ci; For ARC700 SMP, the "global" obviously can't be used for free up the FIRST 5862306a36Sopenharmony_ci; core reg as it will not be SMP safe. 5962306a36Sopenharmony_ci; Thus scratch AUX reg is used (and no longer used to cache task PGD). 6062306a36Sopenharmony_ci; To save the rest of 3 regs - per cpu, the global is made "per-cpu". 6162306a36Sopenharmony_ci; Epilogue thus has to locate the "per-cpu" storage for regs. 6262306a36Sopenharmony_ci; To avoid cache line bouncing the per-cpu global is aligned/sized per 6362306a36Sopenharmony_ci; L1_CACHE_SHIFT, despite fundamentally needing to be 12 bytes only. Hence 6462306a36Sopenharmony_ci; ".size ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT)" 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci; As simple as that.... 6762306a36Sopenharmony_ci;-------------------------------------------------------------------------- 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci; scratch memory to save [r0-r3] used to code TLB refill Handler 7062306a36Sopenharmony_ciARCFP_DATA ex_saved_reg1 7162306a36Sopenharmony_ci .align 1 << L1_CACHE_SHIFT 7262306a36Sopenharmony_ci .type ex_saved_reg1, @object 7362306a36Sopenharmony_ci#ifdef CONFIG_SMP 7462306a36Sopenharmony_ci .size ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT) 7562306a36Sopenharmony_ciex_saved_reg1: 7662306a36Sopenharmony_ci .zero (CONFIG_NR_CPUS << L1_CACHE_SHIFT) 7762306a36Sopenharmony_ci#else 7862306a36Sopenharmony_ci .size ex_saved_reg1, 16 7962306a36Sopenharmony_ciex_saved_reg1: 8062306a36Sopenharmony_ci .zero 16 8162306a36Sopenharmony_ci#endif 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci.macro TLBMISS_FREEUP_REGS 8462306a36Sopenharmony_ci#ifdef CONFIG_SMP 8562306a36Sopenharmony_ci sr r0, [ARC_REG_SCRATCH_DATA0] ; freeup r0 to code with 8662306a36Sopenharmony_ci GET_CPU_ID r0 ; get to per cpu scratch mem, 8762306a36Sopenharmony_ci asl r0, r0, L1_CACHE_SHIFT ; cache line wide per cpu 8862306a36Sopenharmony_ci add r0, @ex_saved_reg1, r0 8962306a36Sopenharmony_ci#else 9062306a36Sopenharmony_ci st r0, [@ex_saved_reg1] 9162306a36Sopenharmony_ci mov_s r0, @ex_saved_reg1 9262306a36Sopenharmony_ci#endif 9362306a36Sopenharmony_ci st_s r1, [r0, 4] 9462306a36Sopenharmony_ci st_s r2, [r0, 8] 9562306a36Sopenharmony_ci st_s r3, [r0, 12] 9662306a36Sopenharmony_ci.endm 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci.macro TLBMISS_RESTORE_REGS 9962306a36Sopenharmony_ci#ifdef CONFIG_SMP 10062306a36Sopenharmony_ci GET_CPU_ID r0 ; get to per cpu scratch mem 10162306a36Sopenharmony_ci asl r0, r0, L1_CACHE_SHIFT ; each is cache line wide 10262306a36Sopenharmony_ci add r0, @ex_saved_reg1, r0 10362306a36Sopenharmony_ci ld_s r3, [r0,12] 10462306a36Sopenharmony_ci ld_s r2, [r0, 8] 10562306a36Sopenharmony_ci ld_s r1, [r0, 4] 10662306a36Sopenharmony_ci lr r0, [ARC_REG_SCRATCH_DATA0] 10762306a36Sopenharmony_ci#else 10862306a36Sopenharmony_ci mov_s r0, @ex_saved_reg1 10962306a36Sopenharmony_ci ld_s r3, [r0,12] 11062306a36Sopenharmony_ci ld_s r2, [r0, 8] 11162306a36Sopenharmony_ci ld_s r1, [r0, 4] 11262306a36Sopenharmony_ci ld_s r0, [r0] 11362306a36Sopenharmony_ci#endif 11462306a36Sopenharmony_ci.endm 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#else /* ARCv2 */ 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci.macro TLBMISS_FREEUP_REGS 11962306a36Sopenharmony_ci#ifdef CONFIG_ARC_HAS_LL64 12062306a36Sopenharmony_ci std r0, [sp, -16] 12162306a36Sopenharmony_ci std r2, [sp, -8] 12262306a36Sopenharmony_ci#else 12362306a36Sopenharmony_ci PUSH r0 12462306a36Sopenharmony_ci PUSH r1 12562306a36Sopenharmony_ci PUSH r2 12662306a36Sopenharmony_ci PUSH r3 12762306a36Sopenharmony_ci#endif 12862306a36Sopenharmony_ci.endm 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci.macro TLBMISS_RESTORE_REGS 13162306a36Sopenharmony_ci#ifdef CONFIG_ARC_HAS_LL64 13262306a36Sopenharmony_ci ldd r0, [sp, -16] 13362306a36Sopenharmony_ci ldd r2, [sp, -8] 13462306a36Sopenharmony_ci#else 13562306a36Sopenharmony_ci POP r3 13662306a36Sopenharmony_ci POP r2 13762306a36Sopenharmony_ci POP r1 13862306a36Sopenharmony_ci POP r0 13962306a36Sopenharmony_ci#endif 14062306a36Sopenharmony_ci.endm 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#endif 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci;============================================================================ 14562306a36Sopenharmony_ci;TLB Miss handling Code 14662306a36Sopenharmony_ci;============================================================================ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci#ifndef PMD_SHIFT 14962306a36Sopenharmony_ci#define PMD_SHIFT PUD_SHIFT 15062306a36Sopenharmony_ci#endif 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#ifndef PUD_SHIFT 15362306a36Sopenharmony_ci#define PUD_SHIFT PGDIR_SHIFT 15462306a36Sopenharmony_ci#endif 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci;----------------------------------------------------------------------------- 15762306a36Sopenharmony_ci; This macro does the page-table lookup for the faulting address. 15862306a36Sopenharmony_ci; OUT: r0 = PTE faulted on, r1 = ptr to PTE, r2 = Faulting V-address 15962306a36Sopenharmony_ci.macro LOAD_FAULT_PTE 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci lr r2, [efa] 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#ifdef CONFIG_ISA_ARCV2 16462306a36Sopenharmony_ci lr r1, [ARC_REG_SCRATCH_DATA0] ; current pgd 16562306a36Sopenharmony_ci#else 16662306a36Sopenharmony_ci GET_CURR_TASK_ON_CPU r1 16762306a36Sopenharmony_ci ld r1, [r1, TASK_ACT_MM] 16862306a36Sopenharmony_ci ld r1, [r1, MM_PGD] 16962306a36Sopenharmony_ci#endif 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci lsr r0, r2, PGDIR_SHIFT ; Bits for indexing into PGD 17262306a36Sopenharmony_ci ld.as r3, [r1, r0] ; PGD entry corresp to faulting addr 17362306a36Sopenharmony_ci tst r3, r3 17462306a36Sopenharmony_ci bz do_slow_path_pf ; if no Page Table, do page fault 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#if CONFIG_PGTABLE_LEVELS > 3 17762306a36Sopenharmony_ci lsr r0, r2, PUD_SHIFT ; Bits for indexing into PUD 17862306a36Sopenharmony_ci and r0, r0, (PTRS_PER_PUD - 1) 17962306a36Sopenharmony_ci ld.as r1, [r3, r0] ; PMD entry 18062306a36Sopenharmony_ci tst r1, r1 18162306a36Sopenharmony_ci bz do_slow_path_pf 18262306a36Sopenharmony_ci mov r3, r1 18362306a36Sopenharmony_ci#endif 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#if CONFIG_PGTABLE_LEVELS > 2 18662306a36Sopenharmony_ci lsr r0, r2, PMD_SHIFT ; Bits for indexing into PMD 18762306a36Sopenharmony_ci and r0, r0, (PTRS_PER_PMD - 1) 18862306a36Sopenharmony_ci ld.as r1, [r3, r0] ; PMD entry 18962306a36Sopenharmony_ci tst r1, r1 19062306a36Sopenharmony_ci bz do_slow_path_pf 19162306a36Sopenharmony_ci mov r3, r1 19262306a36Sopenharmony_ci#endif 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 19562306a36Sopenharmony_ci and.f 0, r3, _PAGE_HW_SZ ; Is this Huge PMD (thp) 19662306a36Sopenharmony_ci add2.nz r1, r1, r0 19762306a36Sopenharmony_ci bnz.d 2f ; YES: PGD == PMD has THP PTE: stop pgd walk 19862306a36Sopenharmony_ci mov.nz r0, r3 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#endif 20162306a36Sopenharmony_ci and r1, r3, PAGE_MASK 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci ; Get the PTE entry: The idea is 20462306a36Sopenharmony_ci ; (1) x = addr >> PAGE_SHIFT -> masks page-off bits from @fault-addr 20562306a36Sopenharmony_ci ; (2) y = x & (PTRS_PER_PTE - 1) -> to get index 20662306a36Sopenharmony_ci ; (3) z = (pgtbl + y * 4) 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#ifdef CONFIG_ARC_HAS_PAE40 20962306a36Sopenharmony_ci#define PTE_SIZE_LOG 3 /* 8 == 2 ^ 3 */ 21062306a36Sopenharmony_ci#else 21162306a36Sopenharmony_ci#define PTE_SIZE_LOG 2 /* 4 == 2 ^ 2 */ 21262306a36Sopenharmony_ci#endif 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci ; multiply in step (3) above avoided by shifting lesser in step (1) 21562306a36Sopenharmony_ci lsr r0, r2, ( PAGE_SHIFT - PTE_SIZE_LOG ) 21662306a36Sopenharmony_ci and r0, r0, ( (PTRS_PER_PTE - 1) << PTE_SIZE_LOG ) 21762306a36Sopenharmony_ci ld.aw r0, [r1, r0] ; r0: PTE (lower word only for PAE40) 21862306a36Sopenharmony_ci ; r1: PTE ptr 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci2: 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci.endm 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci;----------------------------------------------------------------- 22562306a36Sopenharmony_ci; Convert Linux PTE entry into TLB entry 22662306a36Sopenharmony_ci; A one-word PTE entry is programmed as two-word TLB Entry [PD0:PD1] in mmu 22762306a36Sopenharmony_ci; (for PAE40, two-words PTE, while three-word TLB Entry [PD0:PD1:PD1HI]) 22862306a36Sopenharmony_ci; IN: r0 = PTE, r1 = ptr to PTE 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci.macro CONV_PTE_TO_TLB 23162306a36Sopenharmony_ci and r3, r0, PTE_BITS_RWX ; r w x 23262306a36Sopenharmony_ci asl r2, r3, 3 ; Kr Kw Kx 0 0 0 (GLOBAL, kernel only) 23362306a36Sopenharmony_ci and.f 0, r0, _PAGE_GLOBAL 23462306a36Sopenharmony_ci or.z r2, r2, r3 ; Kr Kw Kx Ur Uw Ux (!GLOBAL, user page) 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci and r3, r0, PTE_BITS_NON_RWX_IN_PD1 ; Extract PFN+cache bits from PTE 23762306a36Sopenharmony_ci or r3, r3, r2 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci sr r3, [ARC_REG_TLBPD1] ; paddr[31..13] | Kr Kw Kx Ur Uw Ux | C 24062306a36Sopenharmony_ci#ifdef CONFIG_ARC_HAS_PAE40 24162306a36Sopenharmony_ci ld r3, [r1, 4] ; paddr[39..32] 24262306a36Sopenharmony_ci sr r3, [ARC_REG_TLBPD1HI] 24362306a36Sopenharmony_ci#endif 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci and r2, r0, PTE_BITS_IN_PD0 ; Extract other PTE flags: (V)alid, (G)lb 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci lr r3,[ARC_REG_TLBPD0] ; MMU prepares PD0 with vaddr and asid 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci or r3, r3, r2 ; S | vaddr | {sasid|asid} 25062306a36Sopenharmony_ci sr r3,[ARC_REG_TLBPD0] ; rewrite PD0 25162306a36Sopenharmony_ci.endm 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci;----------------------------------------------------------------- 25462306a36Sopenharmony_ci; Commit the TLB entry into MMU 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci.macro COMMIT_ENTRY_TO_MMU 25762306a36Sopenharmony_ci#ifdef CONFIG_ARC_MMU_V3 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* Get free TLB slot: Set = computed from vaddr, way = random */ 26062306a36Sopenharmony_ci sr TLBGetIndex, [ARC_REG_TLBCOMMAND] 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Commit the Write */ 26362306a36Sopenharmony_ci sr TLBWriteNI, [ARC_REG_TLBCOMMAND] 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci#else 26662306a36Sopenharmony_ci sr TLBInsertEntry, [ARC_REG_TLBCOMMAND] 26762306a36Sopenharmony_ci#endif 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci88: 27062306a36Sopenharmony_ci.endm 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ciARCFP_CODE ;Fast Path Code, candidate for ICCM 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci;----------------------------------------------------------------------------- 27662306a36Sopenharmony_ci; I-TLB Miss Exception Handler 27762306a36Sopenharmony_ci;----------------------------------------------------------------------------- 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ciENTRY(EV_TLBMissI) 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci TLBMISS_FREEUP_REGS 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci ;---------------------------------------------------------------- 28462306a36Sopenharmony_ci ; Get the PTE corresponding to V-addr accessed, r2 is setup with EFA 28562306a36Sopenharmony_ci LOAD_FAULT_PTE 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci ;---------------------------------------------------------------- 28862306a36Sopenharmony_ci ; VERIFY_PTE: Check if PTE permissions approp for executing code 28962306a36Sopenharmony_ci cmp_s r2, VMALLOC_START 29062306a36Sopenharmony_ci mov_s r2, (_PAGE_PRESENT | _PAGE_EXECUTE) 29162306a36Sopenharmony_ci or.hs r2, r2, _PAGE_GLOBAL 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci and r3, r0, r2 ; Mask out NON Flag bits from PTE 29462306a36Sopenharmony_ci xor.f r3, r3, r2 ; check ( ( pte & flags_test ) == flags_test ) 29562306a36Sopenharmony_ci bnz do_slow_path_pf 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci ; Let Linux VM know that the page was accessed 29862306a36Sopenharmony_ci or r0, r0, _PAGE_ACCESSED ; set Accessed Bit 29962306a36Sopenharmony_ci st_s r0, [r1] ; Write back PTE 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci CONV_PTE_TO_TLB 30262306a36Sopenharmony_ci COMMIT_ENTRY_TO_MMU 30362306a36Sopenharmony_ci TLBMISS_RESTORE_REGS 30462306a36Sopenharmony_ciEV_TLBMissI_fast_ret: ; additional label for VDK OS-kit instrumentation 30562306a36Sopenharmony_ci rtie 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ciEND(EV_TLBMissI) 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci;----------------------------------------------------------------------------- 31062306a36Sopenharmony_ci; D-TLB Miss Exception Handler 31162306a36Sopenharmony_ci;----------------------------------------------------------------------------- 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciENTRY(EV_TLBMissD) 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci TLBMISS_FREEUP_REGS 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci ;---------------------------------------------------------------- 31862306a36Sopenharmony_ci ; Get the PTE corresponding to V-addr accessed 31962306a36Sopenharmony_ci ; If PTE exists, it will setup, r0 = PTE, r1 = Ptr to PTE, r2 = EFA 32062306a36Sopenharmony_ci LOAD_FAULT_PTE 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ;---------------------------------------------------------------- 32362306a36Sopenharmony_ci ; VERIFY_PTE: Chk if PTE permissions approp for data access (R/W/R+W) 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci cmp_s r2, VMALLOC_START 32662306a36Sopenharmony_ci mov_s r2, _PAGE_PRESENT ; common bit for K/U PTE 32762306a36Sopenharmony_ci or.hs r2, r2, _PAGE_GLOBAL ; kernel PTE only 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ; Linux PTE [RWX] bits are semantically overloaded: 33062306a36Sopenharmony_ci ; -If PAGE_GLOBAL set, they refer to kernel-only flags (vmalloc) 33162306a36Sopenharmony_ci ; -Otherwise they are user-mode permissions, and those are exactly 33262306a36Sopenharmony_ci ; same for kernel mode as well (e.g. copy_(to|from)_user) 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci lr r3, [ecr] 33562306a36Sopenharmony_ci btst_s r3, ECR_C_BIT_DTLB_LD_MISS ; Read Access 33662306a36Sopenharmony_ci or.nz r2, r2, _PAGE_READ ; chk for Read flag in PTE 33762306a36Sopenharmony_ci btst_s r3, ECR_C_BIT_DTLB_ST_MISS ; Write Access 33862306a36Sopenharmony_ci or.nz r2, r2, _PAGE_WRITE ; chk for Write flag in PTE 33962306a36Sopenharmony_ci ; Above laddering takes care of XCHG access (both R and W) 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci ; By now, r2 setup with all the Flags we need to check in PTE 34262306a36Sopenharmony_ci and r3, r0, r2 ; Mask out NON Flag bits from PTE 34362306a36Sopenharmony_ci brne.d r3, r2, do_slow_path_pf ; is ((pte & flags_test) == flags_test) 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci ;---------------------------------------------------------------- 34662306a36Sopenharmony_ci ; UPDATE_PTE: Let Linux VM know that page was accessed/dirty 34762306a36Sopenharmony_ci or r0, r0, _PAGE_ACCESSED ; Accessed bit always 34862306a36Sopenharmony_ci or.nz r0, r0, _PAGE_DIRTY ; if Write, set Dirty bit as well 34962306a36Sopenharmony_ci st_s r0, [r1] ; Write back PTE 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci CONV_PTE_TO_TLB 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci COMMIT_ENTRY_TO_MMU 35462306a36Sopenharmony_ci TLBMISS_RESTORE_REGS 35562306a36Sopenharmony_ciEV_TLBMissD_fast_ret: ; additional label for VDK OS-kit instrumentation 35662306a36Sopenharmony_ci rtie 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci;-------- Common routine to call Linux Page Fault Handler ----------- 35962306a36Sopenharmony_cido_slow_path_pf: 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci#ifdef CONFIG_ISA_ARCV2 36262306a36Sopenharmony_ci ; Set Z flag if exception in U mode. Hardware micro-ops do this on any 36362306a36Sopenharmony_ci ; taken interrupt/exception, and thus is already the case at the entry 36462306a36Sopenharmony_ci ; above, but ensuing code would have already clobbered. 36562306a36Sopenharmony_ci ; EXCEPTION_PROLOGUE called in slow path, relies on correct Z flag set 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci lr r2, [erstatus] 36862306a36Sopenharmony_ci and r2, r2, STATUS_U_MASK 36962306a36Sopenharmony_ci bxor.f 0, r2, STATUS_U_BIT 37062306a36Sopenharmony_ci#endif 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci ; Restore the 4-scratch regs saved by fast path miss handler 37362306a36Sopenharmony_ci TLBMISS_RESTORE_REGS 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci ; Slow path TLB Miss handled as a regular ARC Exception 37662306a36Sopenharmony_ci ; (stack switching / save the complete reg-file). 37762306a36Sopenharmony_ci b call_do_page_fault 37862306a36Sopenharmony_ciEND(EV_TLBMissD) 379