Commit 48cd6783 authored by Jack Steiner's avatar Jack Steiner Committed by David Mosberger

[PATCH] ia64: Reduce TLB flushing during process migration

This patch adds an architecture-specific callout after explicit
processor migrations.  The callout allows architectures (or platforms)
to update TLB specific information (ex., cpu_vm_mask).
Signed-off-by: default avatarJack Steiner <steiner@sgi.com>
Signed-off-by: default avatarDavid Mosberger <davidm@hpl.hp.com>
parent eac9ee8e
...@@ -132,6 +132,17 @@ changes occur: ...@@ -132,6 +132,17 @@ changes occur:
translations for software managed TLB configurations. translations for software managed TLB configurations.
The sparc64 port currently does this. The sparc64 port currently does this.
7) void tlb_migrate_finish(struct mm_struct *mm)
This interface is called at the end of an explicit
process migration. This interface provides a hook
to allow a platform to update TLB or context-specific
information for the address space.
The ia64 sn2 platform is one example of a platform
that uses this interface.
Next, we have the cache flushing interfaces. In general, when Linux Next, we have the cache flushing interfaces. In general, when Linux
is changing an existing virtual-->physical mapping to a new value, is changing an existing virtual-->physical mapping to a new value,
the sequence will be in one of the following forms: the sequence will be in one of the following forms:
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/tlb.h>
#include <asm/numa.h> #include <asm/numa.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
...@@ -60,6 +61,13 @@ wait_piowc(void) ...@@ -60,6 +61,13 @@ wait_piowc(void)
} }
void
sn_tlb_migrate_finish(struct mm_struct *mm)
{
if (mm == current->mm)
flush_tlb_mm(mm);
}
/** /**
* sn2_global_tlb_purge - globally purge translation cache of virtual address range * sn2_global_tlb_purge - globally purge translation cache of virtual address range
...@@ -114,6 +122,13 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit ...@@ -114,6 +122,13 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit
return; return;
} }
if (atomic_read(&mm->mm_users) == 1) {
flush_tlb_mm(mm);
preempt_enable();
return;
}
nix = 0; nix = 0;
for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES;
cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode))
......
...@@ -147,4 +147,6 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) ...@@ -147,4 +147,6 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
__pmd_free_tlb(tlb, pmdp); \ __pmd_free_tlb(tlb, pmdp); \
} while (0) } while (0)
#define tlb_migrate_finish(mm) do {} while (0)
#endif /* _ASM_GENERIC__TLB_H */ #endif /* _ASM_GENERIC__TLB_H */
...@@ -19,6 +19,7 @@ struct pt_regs; ...@@ -19,6 +19,7 @@ struct pt_regs;
struct scatterlist; struct scatterlist;
struct irq_desc; struct irq_desc;
struct page; struct page;
struct mm_struct;
typedef void ia64_mv_setup_t (char **); typedef void ia64_mv_setup_t (char **);
typedef void ia64_mv_cpu_init_t (void); typedef void ia64_mv_cpu_init_t (void);
...@@ -26,6 +27,7 @@ typedef void ia64_mv_irq_init_t (void); ...@@ -26,6 +27,7 @@ typedef void ia64_mv_irq_init_t (void);
typedef void ia64_mv_send_ipi_t (int, int, int, int); typedef void ia64_mv_send_ipi_t (int, int, int, int);
typedef void ia64_mv_timer_interrupt_t (int, void *, struct pt_regs *); typedef void ia64_mv_timer_interrupt_t (int, void *, struct pt_regs *);
typedef void ia64_mv_global_tlb_purge_t (unsigned long, unsigned long, unsigned long); typedef void ia64_mv_global_tlb_purge_t (unsigned long, unsigned long, unsigned long);
typedef void ia64_mv_tlb_migrate_finish_t (struct mm_struct *);
typedef struct irq_desc *ia64_mv_irq_desc (unsigned int); typedef struct irq_desc *ia64_mv_irq_desc (unsigned int);
typedef u8 ia64_mv_irq_to_vector (u8); typedef u8 ia64_mv_irq_to_vector (u8);
typedef unsigned int ia64_mv_local_vector_to_irq (u8 vector); typedef unsigned int ia64_mv_local_vector_to_irq (u8 vector);
...@@ -74,10 +76,16 @@ machvec_noop (void) ...@@ -74,10 +76,16 @@ machvec_noop (void)
{ {
} }
static inline void
machvec_noop_mm (struct mm_struct *mm)
{
}
extern void machvec_setup (char **); extern void machvec_setup (char **);
extern void machvec_timer_interrupt (int, void *, struct pt_regs *); extern void machvec_timer_interrupt (int, void *, struct pt_regs *);
extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int); extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int);
extern void machvec_dma_sync_sg (struct device *, struct scatterlist *, int, int); extern void machvec_dma_sync_sg (struct device *, struct scatterlist *, int, int);
extern void machvec_tlb_migrate_finish (struct mm_struct *);
# if defined (CONFIG_IA64_HP_SIM) # if defined (CONFIG_IA64_HP_SIM)
# include <asm/machvec_hpsim.h> # include <asm/machvec_hpsim.h>
...@@ -99,6 +107,7 @@ extern void machvec_dma_sync_sg (struct device *, struct scatterlist *, int, int ...@@ -99,6 +107,7 @@ extern void machvec_dma_sync_sg (struct device *, struct scatterlist *, int, int
# define platform_send_ipi ia64_mv.send_ipi # define platform_send_ipi ia64_mv.send_ipi
# define platform_timer_interrupt ia64_mv.timer_interrupt # define platform_timer_interrupt ia64_mv.timer_interrupt
# define platform_global_tlb_purge ia64_mv.global_tlb_purge # define platform_global_tlb_purge ia64_mv.global_tlb_purge
# define platform_tlb_migrate_finish ia64_mv.tlb_migrate_finish
# define platform_dma_init ia64_mv.dma_init # define platform_dma_init ia64_mv.dma_init
# define platform_dma_alloc_coherent ia64_mv.dma_alloc_coherent # define platform_dma_alloc_coherent ia64_mv.dma_alloc_coherent
# define platform_dma_free_coherent ia64_mv.dma_free_coherent # define platform_dma_free_coherent ia64_mv.dma_free_coherent
...@@ -144,6 +153,7 @@ struct ia64_machine_vector { ...@@ -144,6 +153,7 @@ struct ia64_machine_vector {
ia64_mv_send_ipi_t *send_ipi; ia64_mv_send_ipi_t *send_ipi;
ia64_mv_timer_interrupt_t *timer_interrupt; ia64_mv_timer_interrupt_t *timer_interrupt;
ia64_mv_global_tlb_purge_t *global_tlb_purge; ia64_mv_global_tlb_purge_t *global_tlb_purge;
ia64_mv_tlb_migrate_finish_t *tlb_migrate_finish;
ia64_mv_dma_init *dma_init; ia64_mv_dma_init *dma_init;
ia64_mv_dma_alloc_coherent *dma_alloc_coherent; ia64_mv_dma_alloc_coherent *dma_alloc_coherent;
ia64_mv_dma_free_coherent *dma_free_coherent; ia64_mv_dma_free_coherent *dma_free_coherent;
...@@ -185,6 +195,7 @@ struct ia64_machine_vector { ...@@ -185,6 +195,7 @@ struct ia64_machine_vector {
platform_send_ipi, \ platform_send_ipi, \
platform_timer_interrupt, \ platform_timer_interrupt, \
platform_global_tlb_purge, \ platform_global_tlb_purge, \
platform_tlb_migrate_finish, \
platform_dma_init, \ platform_dma_init, \
platform_dma_alloc_coherent, \ platform_dma_alloc_coherent, \
platform_dma_free_coherent, \ platform_dma_free_coherent, \
...@@ -264,6 +275,9 @@ extern ia64_mv_dma_supported swiotlb_dma_supported; ...@@ -264,6 +275,9 @@ extern ia64_mv_dma_supported swiotlb_dma_supported;
#ifndef platform_global_tlb_purge #ifndef platform_global_tlb_purge
# define platform_global_tlb_purge ia64_global_tlb_purge /* default to architected version */ # define platform_global_tlb_purge ia64_global_tlb_purge /* default to architected version */
#endif #endif
#ifndef platform_tlb_migrate_finish
# define platform_tlb_migrate_finish machvec_noop_mm
#endif
#ifndef platform_dma_init #ifndef platform_dma_init
# define platform_dma_init swiotlb_init # define platform_dma_init swiotlb_init
#endif #endif
......
...@@ -39,6 +39,7 @@ extern ia64_mv_irq_init_t sn_irq_init; ...@@ -39,6 +39,7 @@ extern ia64_mv_irq_init_t sn_irq_init;
extern ia64_mv_send_ipi_t sn2_send_IPI; extern ia64_mv_send_ipi_t sn2_send_IPI;
extern ia64_mv_timer_interrupt_t sn_timer_interrupt; extern ia64_mv_timer_interrupt_t sn_timer_interrupt;
extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge; extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge;
extern ia64_mv_tlb_migrate_finish_t sn_tlb_migrate_finish;
extern ia64_mv_irq_desc sn_irq_desc; extern ia64_mv_irq_desc sn_irq_desc;
extern ia64_mv_irq_to_vector sn_irq_to_vector; extern ia64_mv_irq_to_vector sn_irq_to_vector;
extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq; extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
...@@ -83,6 +84,7 @@ extern ia64_mv_dma_supported sn_dma_supported; ...@@ -83,6 +84,7 @@ extern ia64_mv_dma_supported sn_dma_supported;
#define platform_send_ipi sn2_send_IPI #define platform_send_ipi sn2_send_IPI
#define platform_timer_interrupt sn_timer_interrupt #define platform_timer_interrupt sn_timer_interrupt
#define platform_global_tlb_purge sn2_global_tlb_purge #define platform_global_tlb_purge sn2_global_tlb_purge
#define platform_tlb_migrate_finish sn_tlb_migrate_finish
#define platform_pci_fixup sn_pci_fixup #define platform_pci_fixup sn_pci_fixup
#define platform_inb __sn_inb #define platform_inb __sn_inb
#define platform_inw __sn_inw #define platform_inw __sn_inw
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/machvec.h>
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
# define FREE_PTE_NR 2048 # define FREE_PTE_NR 2048
...@@ -211,6 +212,8 @@ __tlb_remove_tlb_entry (struct mmu_gather *tlb, pte_t *ptep, unsigned long addre ...@@ -211,6 +212,8 @@ __tlb_remove_tlb_entry (struct mmu_gather *tlb, pte_t *ptep, unsigned long addre
tlb->end_addr = address + PAGE_SIZE; tlb->end_addr = address + PAGE_SIZE;
} }
#define tlb_migrate_finish(mm) platform_tlb_migrate_finish(mm)
#define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0)
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <asm/tlb.h>
#include <asm/unistd.h> #include <asm/unistd.h>
...@@ -3349,6 +3350,7 @@ int set_cpus_allowed(task_t *p, cpumask_t new_mask) ...@@ -3349,6 +3350,7 @@ int set_cpus_allowed(task_t *p, cpumask_t new_mask)
task_rq_unlock(rq, &flags); task_rq_unlock(rq, &flags);
wake_up_process(rq->migration_thread); wake_up_process(rq->migration_thread);
wait_for_completion(&req.done); wait_for_completion(&req.done);
tlb_migrate_finish(p->mm);
return 0; return 0;
} }
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment