~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/sparc/mm/tlb.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* arch/sparc64/mm/tlb.c
 
2
 *
 
3
 * Copyright (C) 2004 David S. Miller <davem@redhat.com>
 
4
 */
 
5
 
 
6
#include <linux/kernel.h>
 
7
#include <linux/init.h>
 
8
#include <linux/percpu.h>
 
9
#include <linux/mm.h>
 
10
#include <linux/swap.h>
 
11
#include <linux/preempt.h>
 
12
 
 
13
#include <asm/pgtable.h>
 
14
#include <asm/pgalloc.h>
 
15
#include <asm/tlbflush.h>
 
16
#include <asm/cacheflush.h>
 
17
#include <asm/mmu_context.h>
 
18
#include <asm/tlb.h>
 
19
 
 
20
/* Heavily inspired by the ppc64 code.  */
 
21
 
 
22
static DEFINE_PER_CPU(struct tlb_batch, tlb_batch);
 
23
 
 
24
void flush_tlb_pending(void)
 
25
{
 
26
        struct tlb_batch *tb = &get_cpu_var(tlb_batch);
 
27
 
 
28
        if (tb->tlb_nr) {
 
29
                flush_tsb_user(tb);
 
30
 
 
31
                if (CTX_VALID(tb->mm->context)) {
 
32
#ifdef CONFIG_SMP
 
33
                        smp_flush_tlb_pending(tb->mm, tb->tlb_nr,
 
34
                                              &tb->vaddrs[0]);
 
35
#else
 
36
                        __flush_tlb_pending(CTX_HWBITS(tb->mm->context),
 
37
                                            tb->tlb_nr, &tb->vaddrs[0]);
 
38
#endif
 
39
                }
 
40
                tb->tlb_nr = 0;
 
41
        }
 
42
 
 
43
        put_cpu_var(tlb_batch);
 
44
}
 
45
 
 
46
void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 
47
                   pte_t *ptep, pte_t orig, int fullmm)
 
48
{
 
49
        struct tlb_batch *tb = &get_cpu_var(tlb_batch);
 
50
        unsigned long nr;
 
51
 
 
52
        vaddr &= PAGE_MASK;
 
53
        if (pte_exec(orig))
 
54
                vaddr |= 0x1UL;
 
55
 
 
56
        if (tlb_type != hypervisor &&
 
57
            pte_dirty(orig)) {
 
58
                unsigned long paddr, pfn = pte_pfn(orig);
 
59
                struct address_space *mapping;
 
60
                struct page *page;
 
61
 
 
62
                if (!pfn_valid(pfn))
 
63
                        goto no_cache_flush;
 
64
 
 
65
                page = pfn_to_page(pfn);
 
66
                if (PageReserved(page))
 
67
                        goto no_cache_flush;
 
68
 
 
69
                /* A real file page? */
 
70
                mapping = page_mapping(page);
 
71
                if (!mapping)
 
72
                        goto no_cache_flush;
 
73
 
 
74
                paddr = (unsigned long) page_address(page);
 
75
                if ((paddr ^ vaddr) & (1 << 13))
 
76
                        flush_dcache_page_all(mm, page);
 
77
        }
 
78
 
 
79
no_cache_flush:
 
80
 
 
81
        if (fullmm) {
 
82
                put_cpu_var(tlb_batch);
 
83
                return;
 
84
        }
 
85
 
 
86
        nr = tb->tlb_nr;
 
87
 
 
88
        if (unlikely(nr != 0 && mm != tb->mm)) {
 
89
                flush_tlb_pending();
 
90
                nr = 0;
 
91
        }
 
92
 
 
93
        if (nr == 0)
 
94
                tb->mm = mm;
 
95
 
 
96
        tb->vaddrs[nr] = vaddr;
 
97
        tb->tlb_nr = ++nr;
 
98
        if (nr >= TLB_BATCH_NR)
 
99
                flush_tlb_pending();
 
100
 
 
101
        put_cpu_var(tlb_batch);
 
102
}