12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /*
- * arch/sh/mm/tlb-urb.c
- *
- * TLB entry wiring helpers for URB-equipped parts.
- *
- * Copyright (C) 2010 Matt Fleming
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
- #include <linux/mm.h>
- #include <linux/io.h>
- #include <asm/tlb.h>
- #include <asm/mmu_context.h>
- /*
- * Load the entry for 'addr' into the TLB and wire the entry.
- */
- void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
- {
- unsigned long status, flags;
- int urb;
- local_irq_save(flags);
- status = __raw_readl(MMUCR);
- urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
- status &= ~MMUCR_URC;
- /*
- * Make sure we're not trying to wire the last TLB entry slot.
- */
- BUG_ON(!--urb);
- urb = urb % MMUCR_URB_NENTRIES;
- /*
- * Insert this entry into the highest non-wired TLB slot (via
- * the URC field).
- */
- status |= (urb << MMUCR_URC_SHIFT);
- __raw_writel(status, MMUCR);
- ctrl_barrier();
- /* Load the entry into the TLB */
- __update_tlb(vma, addr, pte);
- /* ... and wire it up. */
- status = __raw_readl(MMUCR);
- status &= ~MMUCR_URB;
- status |= (urb << MMUCR_URB_SHIFT);
- __raw_writel(status, MMUCR);
- ctrl_barrier();
- local_irq_restore(flags);
- }
- /*
- * Unwire the last wired TLB entry.
- *
- * It should also be noted that it is not possible to wire and unwire
- * TLB entries in an arbitrary order. If you wire TLB entry N, followed
- * by entry N+1, you must unwire entry N+1 first, then entry N. In this
- * respect, it works like a stack or LIFO queue.
- */
- void tlb_unwire_entry(void)
- {
- unsigned long status, flags;
- int urb;
- local_irq_save(flags);
- status = __raw_readl(MMUCR);
- urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
- status &= ~MMUCR_URB;
- /*
- * Make sure we're not trying to unwire a TLB entry when none
- * have been wired.
- */
- BUG_ON(urb++ == MMUCR_URB_NENTRIES);
- urb = urb % MMUCR_URB_NENTRIES;
- status |= (urb << MMUCR_URB_SHIFT);
- __raw_writel(status, MMUCR);
- ctrl_barrier();
- local_irq_restore(flags);
- }
|