linux/arch/arm/kernel/smp_tlb.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/kernel/smp_tlb.c
   3 *
   4 *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10#include <linux/preempt.h>
  11#include <linux/smp.h>
  12
  13#include <asm/smp_plat.h>
  14#include <asm/tlbflush.h>
  15
  16/**********************************************************************/
  17
  18/*
  19 * TLB operations
  20 */
  21struct tlb_args {
  22        struct vm_area_struct *ta_vma;
  23        unsigned long ta_start;
  24        unsigned long ta_end;
  25};
  26
  27static inline void ipi_flush_tlb_all(void *ignored)
  28{
  29        local_flush_tlb_all();
  30}
  31
  32static inline void ipi_flush_tlb_mm(void *arg)
  33{
  34        struct mm_struct *mm = (struct mm_struct *)arg;
  35
  36        local_flush_tlb_mm(mm);
  37}
  38
  39static inline void ipi_flush_tlb_page(void *arg)
  40{
  41        struct tlb_args *ta = (struct tlb_args *)arg;
  42
  43        local_flush_tlb_page(ta->ta_vma, ta->ta_start);
  44}
  45
  46static inline void ipi_flush_tlb_kernel_page(void *arg)
  47{
  48        struct tlb_args *ta = (struct tlb_args *)arg;
  49
  50        local_flush_tlb_kernel_page(ta->ta_start);
  51}
  52
  53static inline void ipi_flush_tlb_range(void *arg)
  54{
  55        struct tlb_args *ta = (struct tlb_args *)arg;
  56
  57        local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
  58}
  59
  60static inline void ipi_flush_tlb_kernel_range(void *arg)
  61{
  62        struct tlb_args *ta = (struct tlb_args *)arg;
  63
  64        local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
  65}
  66
  67void flush_tlb_all(void)
  68{
  69        if (tlb_ops_need_broadcast())
  70                on_each_cpu(ipi_flush_tlb_all, NULL, 1);
  71        else
  72                local_flush_tlb_all();
  73}
  74
  75void flush_tlb_mm(struct mm_struct *mm)
  76{
  77        if (tlb_ops_need_broadcast())
  78                on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
  79        else
  80                local_flush_tlb_mm(mm);
  81}
  82
  83void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
  84{
  85        if (tlb_ops_need_broadcast()) {
  86                struct tlb_args ta;
  87                ta.ta_vma = vma;
  88                ta.ta_start = uaddr;
  89                on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page,
  90                                        &ta, 1);
  91        } else
  92                local_flush_tlb_page(vma, uaddr);
  93}
  94
  95void flush_tlb_kernel_page(unsigned long kaddr)
  96{
  97        if (tlb_ops_need_broadcast()) {
  98                struct tlb_args ta;
  99                ta.ta_start = kaddr;
 100                on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
 101        } else
 102                local_flush_tlb_kernel_page(kaddr);
 103}
 104
 105void flush_tlb_range(struct vm_area_struct *vma,
 106                     unsigned long start, unsigned long end)
 107{
 108        if (tlb_ops_need_broadcast()) {
 109                struct tlb_args ta;
 110                ta.ta_vma = vma;
 111                ta.ta_start = start;
 112                ta.ta_end = end;
 113                on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range,
 114                                        &ta, 1);
 115        } else
 116                local_flush_tlb_range(vma, start, end);
 117}
 118
 119void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 120{
 121        if (tlb_ops_need_broadcast()) {
 122                struct tlb_args ta;
 123                ta.ta_start = start;
 124                ta.ta_end = end;
 125                on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
 126        } else
 127                local_flush_tlb_kernel_range(start, end);
 128}
 129
 130