linux/arch/s390/include/asm/tlbflush.h
<<
>>
Prefs
   1#ifndef _S390_TLBFLUSH_H
   2#define _S390_TLBFLUSH_H
   3
   4#include <linux/mm.h>
   5#include <linux/sched.h>
   6#include <asm/processor.h>
   7#include <asm/pgalloc.h>
   8
   9/*
  10 * Flush all tlb entries on the local cpu.
  11 */
  12static inline void __tlb_flush_local(void)
  13{
  14        asm volatile("ptlb" : : : "memory");
  15}
  16
  17#ifdef CONFIG_SMP
  18/*
  19 * Flush all tlb entries on all cpus.
  20 */
  21void smp_ptlb_all(void);
  22
  23static inline void __tlb_flush_global(void)
  24{
  25        register unsigned long reg2 asm("2");
  26        register unsigned long reg3 asm("3");
  27        register unsigned long reg4 asm("4");
  28        long dummy;
  29
  30#ifndef __s390x__
  31        if (!MACHINE_HAS_CSP) {
  32                smp_ptlb_all();
  33                return;
  34        }
  35#endif /* __s390x__ */
  36
  37        dummy = 0;
  38        reg2 = reg3 = 0;
  39        reg4 = ((unsigned long) &dummy) + 1;
  40        asm volatile(
  41                "       csp     %0,%2"
  42                : : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
  43}
  44
  45static inline void __tlb_flush_full(struct mm_struct *mm)
  46{
  47        cpumask_t local_cpumask;
  48
  49        preempt_disable();
  50        /*
  51         * If the process only ran on the local cpu, do a local flush.
  52         */
  53        local_cpumask = cpumask_of_cpu(smp_processor_id());
  54        if (cpumask_equal(mm_cpumask(mm), &local_cpumask))
  55                __tlb_flush_local();
  56        else
  57                __tlb_flush_global();
  58        preempt_enable();
  59}
  60#else
  61#define __tlb_flush_full(mm)    __tlb_flush_local()
  62#endif
  63
  64/*
  65 * Flush all tlb entries of a page table on all cpus.
  66 */
  67static inline void __tlb_flush_idte(unsigned long asce)
  68{
  69        asm volatile(
  70                "       .insn   rrf,0xb98e0000,0,%0,%1,0"
  71                : : "a" (2048), "a" (asce) : "cc" );
  72}
  73
  74static inline void __tlb_flush_mm(struct mm_struct * mm)
  75{
  76        if (unlikely(cpumask_empty(mm_cpumask(mm))))
  77                return;
  78        /*
  79         * If the machine has IDTE we prefer to do a per mm flush
  80         * on all cpus instead of doing a local flush if the mm
  81         * only ran on the local cpu.
  82         */
  83        if (MACHINE_HAS_IDTE) {
  84                if (mm->context.noexec)
  85                        __tlb_flush_idte((unsigned long)
  86                                         get_shadow_table(mm->pgd) |
  87                                         mm->context.asce_bits);
  88                __tlb_flush_idte((unsigned long) mm->pgd |
  89                                 mm->context.asce_bits);
  90                return;
  91        }
  92        __tlb_flush_full(mm);
  93}
  94
  95static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
  96{
  97        spin_lock(&mm->page_table_lock);
  98        if (mm->context.flush_mm) {
  99                __tlb_flush_mm(mm);
 100                mm->context.flush_mm = 0;
 101        }
 102        spin_unlock(&mm->page_table_lock);
 103}
 104
 105/*
 106 * TLB flushing:
 107 *  flush_tlb() - flushes the current mm struct TLBs
 108 *  flush_tlb_all() - flushes all processes TLBs
 109 *  flush_tlb_mm(mm) - flushes the specified mm context TLB's
 110 *  flush_tlb_page(vma, vmaddr) - flushes one page
 111 *  flush_tlb_range(vma, start, end) - flushes a range of pages
 112 *  flush_tlb_kernel_range(start, end) - flushes a range of kernel pages
 113 */
 114
 115/*
 116 * flush_tlb_mm goes together with ptep_set_wrprotect for the
 117 * copy_page_range operation and flush_tlb_range is related to
 118 * ptep_get_and_clear for change_protection. ptep_set_wrprotect and
 119 * ptep_get_and_clear do not flush the TLBs directly if the mm has
 120 * only one user. At the end of the update the flush_tlb_mm and
 121 * flush_tlb_range functions need to do the flush.
 122 */
 123#define flush_tlb()                             do { } while (0)
 124#define flush_tlb_all()                         do { } while (0)
 125#define flush_tlb_page(vma, addr)               do { } while (0)
 126
 127static inline void flush_tlb_mm(struct mm_struct *mm)
 128{
 129        __tlb_flush_mm_cond(mm);
 130}
 131
 132static inline void flush_tlb_range(struct vm_area_struct *vma,
 133                                   unsigned long start, unsigned long end)
 134{
 135        __tlb_flush_mm_cond(vma->vm_mm);
 136}
 137
 138static inline void flush_tlb_kernel_range(unsigned long start,
 139                                          unsigned long end)
 140{
 141        __tlb_flush_mm(&init_mm);
 142}
 143
 144#endif /* _S390_TLBFLUSH_H */
 145