tlb.h 3.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
#ifndef __UM_TLB_H
#define __UM_TLB_H

W
WANG Cong 已提交
4
#include <linux/pagemap.h>
J
Jeff Dike 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include <linux/swap.h>
#include <asm/percpu.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>

#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)

/* struct mmu_gather is an opaque type used by the mm code for passing around
 * any data needed by arch specific code for tlb_remove_page.
 */
struct mmu_gather {
	struct mm_struct	*mm;
	unsigned int		need_flush; /* Really unmapped some ptes? */
	unsigned long		start;
	unsigned long		end;
	unsigned int		fullmm; /* non-zero means full mm flush */
};

static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
					  unsigned long address)
{
	if (tlb->start > address)
		tlb->start = address;
	if (tlb->end < address + PAGE_SIZE)
		tlb->end = address + PAGE_SIZE;
}

static inline void init_tlb_gather(struct mmu_gather *tlb)
{
	tlb->need_flush = 0;

	tlb->start = TASK_SIZE;
	tlb->end = 0;

	if (tlb->fullmm) {
		tlb->start = 0;
		tlb->end = TASK_SIZE;
	}
}

P
Peter Zijlstra 已提交
47
static inline void
48
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
J
Jeff Dike 已提交
49 50
{
	tlb->mm = mm;
51 52 53
	tlb->start = start;
	tlb->end = end;
	tlb->fullmm = !(start | (end+1));
J
Jeff Dike 已提交
54 55 56 57 58 59 60

	init_tlb_gather(tlb);
}

extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
			       unsigned long end);

61 62 63 64 65 66 67 68 69 70 71 72
static inline void
tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
{
	flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end);
}

static inline void
tlb_flush_mmu_free(struct mmu_gather *tlb)
{
	init_tlb_gather(tlb);
}

J
Jeff Dike 已提交
73
static inline void
P
Peter Zijlstra 已提交
74
tlb_flush_mmu(struct mmu_gather *tlb)
J
Jeff Dike 已提交
75 76 77 78
{
	if (!tlb->need_flush)
		return;

79 80
	tlb_flush_mmu_tlbonly(tlb);
	tlb_flush_mmu_free(tlb);
J
Jeff Dike 已提交
81 82 83 84 85 86 87 88 89
}

/* tlb_finish_mmu
 *	Called at the end of the shootdown operation to free up any resources
 *	that were required.
 */
static inline void
tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
P
Peter Zijlstra 已提交
90
	tlb_flush_mmu(tlb);
J
Jeff Dike 已提交
91 92 93 94 95 96 97 98 99 100

	/* keep the page table cache within bounds */
	check_pgt_cache();
}

/* tlb_remove_page
 *	Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)),
 *	while handling the additional races in SMP caused by other CPUs
 *	caching valid mappings in their TLBs.
 */
P
Peter Zijlstra 已提交
101
static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
J
Jeff Dike 已提交
102 103 104
{
	tlb->need_flush = 1;
	free_page_and_swap_cache(page);
P
Peter Zijlstra 已提交
105 106 107 108 109 110
	return 1; /* avoid calling tlb_flush_mmu */
}

static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
{
	__tlb_remove_page(tlb, page);
J
Jeff Dike 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
}

/**
 * tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation.
 *
 * Record the fact that pte's were really umapped in ->need_flush, so we can
 * later optimise away the tlb invalidate.   This helps when userspace is
 * unmapping already-unmapped pages, which happens quite a lot.
 */
#define tlb_remove_tlb_entry(tlb, ptep, address)		\
	do {							\
		tlb->need_flush = 1;				\
		__tlb_remove_tlb_entry(tlb, ptep, address);	\
	} while (0)

126
#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
J
Jeff Dike 已提交
127

128
#define pud_free_tlb(tlb, pudp, addr) __pud_free_tlb(tlb, pudp, addr)
J
Jeff Dike 已提交
129

130
#define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr)
J
Jeff Dike 已提交
131 132

#define tlb_migrate_finish(mm) do {} while (0)
L
Linus Torvalds 已提交
133 134

#endif