diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-29 20:59:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-29 20:59:55 -0700 |
commit | 92dd7ca0af8f769569bde98a83b4a8f4daec6ac5 (patch) | |
tree | 9217bee214128a4a45b2e0a3d9784d05fea2c8fb /arch/arm/kernel/smp.c | |
parent | 164cad9bacc2cf190493d2ee4918dc2869ba6f53 (diff) | |
parent | da41119af78864d27ccbf505949df788d5e8aaf5 (diff) |
Merge master.kernel.org:/home/rmk/linux-2.6-arm
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r-- | arch/arm/kernel/smp.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 34892758f09..a931409c8fe 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -502,3 +502,126 @@ int __init setup_profiling_timer(unsigned int multiplier) { return -EINVAL; } + +static int +on_each_cpu_mask(void (*func)(void *), void *info, int retry, int wait, + cpumask_t mask) +{ + int ret = 0; + + preempt_disable(); + + ret = smp_call_function_on_cpu(func, info, retry, wait, mask); + if (cpu_isset(smp_processor_id(), mask)) + func(info); + + preempt_enable(); + + return ret; +} + +/**********************************************************************/ + +/* + * TLB operations + */ +struct tlb_args { + struct vm_area_struct *ta_vma; + unsigned long ta_start; + unsigned long ta_end; +}; + +static inline void ipi_flush_tlb_all(void *ignored) +{ + local_flush_tlb_all(); +} + +static inline void ipi_flush_tlb_mm(void *arg) +{ + struct mm_struct *mm = (struct mm_struct *)arg; + + local_flush_tlb_mm(mm); +} + +static inline void ipi_flush_tlb_page(void *arg) +{ + struct tlb_args *ta = (struct tlb_args *)arg; + + local_flush_tlb_page(ta->ta_vma, ta->ta_start); +} + +static inline void ipi_flush_tlb_kernel_page(void *arg) +{ + struct tlb_args *ta = (struct tlb_args *)arg; + + local_flush_tlb_kernel_page(ta->ta_start); +} + +static inline void ipi_flush_tlb_range(void *arg) +{ + struct tlb_args *ta = (struct tlb_args *)arg; + + local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); +} + +static inline void ipi_flush_tlb_kernel_range(void *arg) +{ + struct tlb_args *ta = (struct tlb_args *)arg; + + local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); +} + +void flush_tlb_all(void) +{ + on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1); +} + +void flush_tlb_mm(struct mm_struct *mm) +{ + cpumask_t mask = mm->cpu_vm_mask; + + on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, 1, mask); +} + +void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) +{ + cpumask_t mask = vma->vm_mm->cpu_vm_mask; + struct tlb_args ta; + + ta.ta_vma = vma; + ta.ta_start = uaddr; + + on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, 1, mask); +} + +void flush_tlb_kernel_page(unsigned long kaddr) +{ + struct tlb_args ta; + + ta.ta_start = kaddr; + + on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1, 1); +} + +void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + cpumask_t mask = vma->vm_mm->cpu_vm_mask; + struct tlb_args ta; + + ta.ta_vma = vma; + ta.ta_start = start; + ta.ta_end = end; + + on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, 1, mask); +} + +void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + struct tlb_args ta; + + ta.ta_start = start; + ta.ta_end = end; + + on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1, 1); +} |