tlb-sh4.c (2598B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * arch/sh/mm/tlb-sh4.c 4 * 5 * SH-4 specific TLB operations 6 * 7 * Copyright (C) 1999 Niibe Yutaka 8 * Copyright (C) 2002 - 2007 Paul Mundt 9 */ 10#include <linux/kernel.h> 11#include <linux/mm.h> 12#include <linux/io.h> 13#include <asm/mmu_context.h> 14#include <asm/cacheflush.h> 15 16void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) 17{ 18 unsigned long flags, pteval, vpn; 19 20 /* 21 * Handle debugger faulting in for debugee. 22 */ 23 if (vma && current->active_mm != vma->vm_mm) 24 return; 25 26 local_irq_save(flags); 27 28 /* Set PTEH register */ 29 vpn = (address & MMU_VPN_MASK) | get_asid(); 30 __raw_writel(vpn, MMU_PTEH); 31 32 pteval = pte.pte_low; 33 34 /* Set PTEA register */ 35#ifdef CONFIG_X2TLB 36 /* 37 * For the extended mode TLB this is trivial, only the ESZ and 38 * EPR bits need to be written out to PTEA, with the remainder of 39 * the protection bits (with the exception of the compat-mode SZ 40 * and PR bits, which are cleared) being written out in PTEL. 41 */ 42 __raw_writel(pte.pte_high, MMU_PTEA); 43#else 44 if (cpu_data->flags & CPU_HAS_PTEA) { 45 /* The last 3 bits and the first one of pteval contains 46 * the PTEA timing control and space attribute bits 47 */ 48 __raw_writel(copy_ptea_attributes(pteval), MMU_PTEA); 49 } 50#endif 51 52 /* Set PTEL register */ 53 pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ 54#ifdef CONFIG_CACHE_WRITETHROUGH 55 pteval |= _PAGE_WT; 56#endif 57 /* conveniently, we want all the software flags to be 0 anyway */ 58 __raw_writel(pteval, MMU_PTEL); 59 60 /* Load the TLB */ 61 asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); 62 local_irq_restore(flags); 63} 64 65void local_flush_tlb_one(unsigned long asid, unsigned long page) 66{ 67 unsigned long addr, data; 68 69 /* 70 * NOTE: PTEH.ASID should be set to this MM 71 * _AND_ we need to write ASID to the array. 72 * 73 * It would be simple if we didn't need to set PTEH.ASID... 74 */ 75 addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; 76 data = page | asid; /* VALID bit is off */ 77 jump_to_uncached(); 78 __raw_writel(data, addr); 79 back_to_cached(); 80} 81 82void local_flush_tlb_all(void) 83{ 84 unsigned long flags, status; 85 int i; 86 87 /* 88 * Flush all the TLB. 89 */ 90 local_irq_save(flags); 91 jump_to_uncached(); 92 93 status = __raw_readl(MMUCR); 94 status = ((status & MMUCR_URB) >> MMUCR_URB_SHIFT); 95 96 if (status == 0) 97 status = MMUCR_URB_NENTRIES; 98 99 for (i = 0; i < status; i++) 100 __raw_writel(0x0, MMU_UTLB_ADDRESS_ARRAY | (i << 8)); 101 102 for (i = 0; i < 4; i++) 103 __raw_writel(0x0, MMU_ITLB_ADDRESS_ARRAY | (i << 8)); 104 105 back_to_cached(); 106 ctrl_barrier(); 107 local_irq_restore(flags); 108}