1 /* 2 * arch/sh/mm/tlb-urb.c 3 * 4 * TLB entry wiring helpers for URB-equipped parts. 5 * 6 * Copyright (C) 2010 Matt Fleming 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 #include <linux/mm.h> 13 #include <linux/io.h> 14 #include <asm/tlb.h> 15 #include <asm/mmu_context.h> 16 17 /* 18 * Load the entry for 'addr' into the TLB and wire the entry. 19 */ 20 void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte) 21 { 22 unsigned long status, flags; 23 int urb; 24 25 local_irq_save(flags); 26 27 status = __raw_readl(MMUCR); 28 urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT; 29 status &= ~MMUCR_URC; 30 31 /* 32 * Make sure we're not trying to wire the last TLB entry slot. 33 */ 34 BUG_ON(!--urb); 35 36 urb = urb % MMUCR_URB_NENTRIES; 37 38 /* 39 * Insert this entry into the highest non-wired TLB slot (via 40 * the URC field). 41 */ 42 status |= (urb << MMUCR_URC_SHIFT); 43 __raw_writel(status, MMUCR); 44 ctrl_barrier(); 45 46 /* Load the entry into the TLB */ 47 __update_tlb(vma, addr, pte); 48 49 /* ... and wire it up. */ 50 status = __raw_readl(MMUCR); 51 52 status &= ~MMUCR_URB; 53 status |= (urb << MMUCR_URB_SHIFT); 54 55 __raw_writel(status, MMUCR); 56 ctrl_barrier(); 57 58 local_irq_restore(flags); 59 } 60 61 /* 62 * Unwire the last wired TLB entry. 63 * 64 * It should also be noted that it is not possible to wire and unwire 65 * TLB entries in an arbitrary order. If you wire TLB entry N, followed 66 * by entry N+1, you must unwire entry N+1 first, then entry N. In this 67 * respect, it works like a stack or LIFO queue. 68 */ 69 void tlb_unwire_entry(void) 70 { 71 unsigned long status, flags; 72 int urb; 73 74 local_irq_save(flags); 75 76 status = __raw_readl(MMUCR); 77 urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT; 78 status &= ~MMUCR_URB; 79 80 /* 81 * Make sure we're not trying to unwire a TLB entry when none 82 * have been wired. 83 */ 84 BUG_ON(urb++ == MMUCR_URB_NENTRIES); 85 86 urb = urb % MMUCR_URB_NENTRIES; 87 88 status |= (urb << MMUCR_URB_SHIFT); 89 __raw_writel(status, MMUCR); 90 ctrl_barrier(); 91 92 local_irq_restore(flags); 93 } 94