ARM: SMP: split out software TLB maintainence broadcasting
smp.c is becoming too large, so split out the TLB maintainence broadcasting into a separate smp_tlb.c file. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
10034aabca
commit
03b505eae6
3 changed files with 140 additions and 127 deletions
|
@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o
|
||||||
obj-$(CONFIG_ARTHUR) += arthur.o
|
obj-$(CONFIG_ARTHUR) += arthur.o
|
||||||
obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
||||||
obj-$(CONFIG_PCI) += bios32.o isa.o
|
obj-$(CONFIG_PCI) += bios32.o isa.o
|
||||||
obj-$(CONFIG_SMP) += smp.o
|
obj-$(CONFIG_SMP) += smp.o smp_tlb.o
|
||||||
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
|
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
|
||||||
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
|
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/localtimer.h>
|
#include <asm/localtimer.h>
|
||||||
#include <asm/smp_plat.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* as from 2.5, kernels no longer have an init_tasks structure
|
* as from 2.5, kernels no longer have an init_tasks structure
|
||||||
|
@ -655,128 +654,3 @@ int setup_profiling_timer(unsigned int multiplier)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
on_each_cpu_mask(void (*func)(void *), void *info, int wait,
|
|
||||||
const struct cpumask *mask)
|
|
||||||
{
|
|
||||||
preempt_disable();
|
|
||||||
|
|
||||||
smp_call_function_many(mask, func, info, wait);
|
|
||||||
if (cpumask_test_cpu(smp_processor_id(), mask))
|
|
||||||
func(info);
|
|
||||||
|
|
||||||
preempt_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
if (tlb_ops_need_broadcast())
|
|
||||||
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
|
|
||||||
else
|
|
||||||
local_flush_tlb_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush_tlb_mm(struct mm_struct *mm)
|
|
||||||
{
|
|
||||||
if (tlb_ops_need_broadcast())
|
|
||||||
on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
|
|
||||||
else
|
|
||||||
local_flush_tlb_mm(mm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
|
|
||||||
{
|
|
||||||
if (tlb_ops_need_broadcast()) {
|
|
||||||
struct tlb_args ta;
|
|
||||||
ta.ta_vma = vma;
|
|
||||||
ta.ta_start = uaddr;
|
|
||||||
on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
|
|
||||||
} else
|
|
||||||
local_flush_tlb_page(vma, uaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush_tlb_kernel_page(unsigned long kaddr)
|
|
||||||
{
|
|
||||||
if (tlb_ops_need_broadcast()) {
|
|
||||||
struct tlb_args ta;
|
|
||||||
ta.ta_start = kaddr;
|
|
||||||
on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
|
|
||||||
} else
|
|
||||||
local_flush_tlb_kernel_page(kaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush_tlb_range(struct vm_area_struct *vma,
|
|
||||||
unsigned long start, unsigned long end)
|
|
||||||
{
|
|
||||||
if (tlb_ops_need_broadcast()) {
|
|
||||||
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, mm_cpumask(vma->vm_mm));
|
|
||||||
} else
|
|
||||||
local_flush_tlb_range(vma, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
|
||||||
{
|
|
||||||
if (tlb_ops_need_broadcast()) {
|
|
||||||
struct tlb_args ta;
|
|
||||||
ta.ta_start = start;
|
|
||||||
ta.ta_end = end;
|
|
||||||
on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
|
|
||||||
} else
|
|
||||||
local_flush_tlb_kernel_range(start, end);
|
|
||||||
}
|
|
||||||
|
|
139
arch/arm/kernel/smp_tlb.c
Normal file
139
arch/arm/kernel/smp_tlb.c
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* linux/arch/arm/kernel/smp_tlb.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
#include <linux/preempt.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
|
||||||
|
#include <asm/smp_plat.h>
|
||||||
|
#include <asm/tlbflush.h>
|
||||||
|
|
||||||
|
static void on_each_cpu_mask(void (*func)(void *), void *info, int wait,
|
||||||
|
const struct cpumask *mask)
|
||||||
|
{
|
||||||
|
preempt_disable();
|
||||||
|
|
||||||
|
smp_call_function_many(mask, func, info, wait);
|
||||||
|
if (cpumask_test_cpu(smp_processor_id(), mask))
|
||||||
|
func(info);
|
||||||
|
|
||||||
|
preempt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
if (tlb_ops_need_broadcast())
|
||||||
|
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
|
||||||
|
else
|
||||||
|
local_flush_tlb_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_tlb_mm(struct mm_struct *mm)
|
||||||
|
{
|
||||||
|
if (tlb_ops_need_broadcast())
|
||||||
|
on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
|
||||||
|
else
|
||||||
|
local_flush_tlb_mm(mm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
|
||||||
|
{
|
||||||
|
if (tlb_ops_need_broadcast()) {
|
||||||
|
struct tlb_args ta;
|
||||||
|
ta.ta_vma = vma;
|
||||||
|
ta.ta_start = uaddr;
|
||||||
|
on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
|
||||||
|
} else
|
||||||
|
local_flush_tlb_page(vma, uaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_tlb_kernel_page(unsigned long kaddr)
|
||||||
|
{
|
||||||
|
if (tlb_ops_need_broadcast()) {
|
||||||
|
struct tlb_args ta;
|
||||||
|
ta.ta_start = kaddr;
|
||||||
|
on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
|
||||||
|
} else
|
||||||
|
local_flush_tlb_kernel_page(kaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_tlb_range(struct vm_area_struct *vma,
|
||||||
|
unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
if (tlb_ops_need_broadcast()) {
|
||||||
|
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, mm_cpumask(vma->vm_mm));
|
||||||
|
} else
|
||||||
|
local_flush_tlb_range(vma, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
if (tlb_ops_need_broadcast()) {
|
||||||
|
struct tlb_args ta;
|
||||||
|
ta.ta_start = start;
|
||||||
|
ta.ta_end = end;
|
||||||
|
on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
|
||||||
|
} else
|
||||||
|
local_flush_tlb_kernel_range(start, end);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue