linux/arch/sh/mm/tlb-urb.c
<<
>>
Prefs
   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 */
  20void 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 */
  69void 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